Changes in / [b21c77a:97397a26]


Ignore:
Files:
7 added
22 deleted
121 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/TestRegen

    rb21c77a r97397a26  
    3333                        email()
    3434                }
    35         }
     35        } 
    3636        catch (Exception caughtError) {
    3737                email_error()
     
    6565
    6666        def install_dir = pwd tmp: true
    67 
     67               
    6868        //Configure the conpilation (Output is not relevant)
    6969        //Use the current directory as the installation target so nothing
     
    101101                def email_subject = "[cforall dashboard][TEST REGEN# ${env.BUILD_NUMBER}] - Result"
    102102                def email_body = """This is an automated email from the Jenkins build machine. It was
    103 generated https://cforall.uwaterloo.ca:8082/dashboard.html.
     103generated http://plg2:8082/dashboard.
    104104
    105105Please apply the required changes using the following method :
     
    118118        def email_subject = "[cforall dashboard][TEST REGEN# ${env.BUILD_NUMBER}] - FAILURE"
    119119        def email_body = """This is an automated email from the Jenkins build machine. It was
    120 generated https://cforall.uwaterloo.ca:8082/dashboard.html.
     120generated http://plg2:8082/dashboard.
    121121
    122122Test generation encoutered an error please see attached logs
  • Jenkinsfile

    rb21c77a r97397a26  
    174174
    175175def notify_server(int wait) {
    176         sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
     176        sh """curl --data "wait=${wait}" -X POST http://plg2:8082/jenkins/notify > /dev/null || true"""
    177177        return
    178178}
     
    329329
    330330                //Then publish the results
    331                 sh 'curl -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
     331                sh 'curl -H \'Content-Type: application/json\' --data @bench.json http://plg2:8082/jenkins/publish > /dev/null || true'
    332332        }
    333333}
  • README

    rb21c77a r97397a26  
    107107- the implicit coercion of structure types to the type of their first member is
    108108  not implemented
    109 
     109       
    110110Who is responsible for cfa-cc?
    111111------------------------------
     
    115115The Cforall project maintains a web page:
    116116
    117         https://cforall.uwaterloo.ca
     117        http://plg.uwaterloo.ca/~cforall
  • doc/papers/OOPSLA17/Makefile

    rb21c77a r97397a26  
    3333
    3434DOCUMENT = generic_types.pdf
    35 BASE = ${basename ${DOCUMENT}}
    3635
    3736# Directives #
     
    4241
    4342clean :
    44         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     43        @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
    4544
    4645# File Dependencies #
    4746
    48 ${DOCUMENT} : ${BASE}.ps
     47${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    4948        ps2pdf $<
    5049
    51 ${BASE}.ps : ${BASE}.dvi
     50${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    5251        dvips ${Build}/$< -o $@
    5352
    54 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    55                 ../../bibliography/pl.bib | ${Build}
     53${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ../../bibliography/pl.bib
    5654        # Must have *.aux file containing citations for bibtex
    5755        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6563## Define the default recipes.
    6664
    67 ${Build} :
     65${Build}:
    6866        mkdir -p ${Build}
    6967
     
    7169        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    7270
    73 %.tex : %.fig | ${Build}
     71%.tex : %.fig
    7472        fig2dev -L eepic $< > ${Build}/$@
    7573
    76 %.ps : %.fig | ${Build}
     74%.ps : %.fig
    7775        fig2dev -L ps $< > ${Build}/$@
    7876
    79 %.pstex : %.fig | ${Build}
     77%.pstex : %.fig
    8078        fig2dev -L pstex $< > ${Build}/$@
    8179        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Makefile

    rb21c77a r97397a26  
    2020
    2121FIGURES = ${addsuffix .tex, \
     22monitor \
     23ext_monitor \
    2224int_monitor \
    2325dependency \
     
    2527
    2628PICTURES = ${addsuffix .pstex, \
    27 monitor \
    28 ext_monitor \
    2929system \
    3030monitor_structs \
     
    5959        dvips ${Build}/$< -o $@
    6060
    61 ${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 annex/local.bib ../../bibliography/pl.bib | ${Build}
     61${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                annex/local.bib ../../bibliography/pl.bib
    6363        # Must have *.aux file containing citations for bibtex
    6464        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    65         -${BibTeX} ${Build}/${basename $@}
     65        ${BibTeX} ${Build}/${basename $@}
    6666        # Some citations reference others so run again to resolve these citations
    6767        ${LaTeX} ${basename $@}.tex
    68         -${BibTeX} ${Build}/${basename $@}
     68        ${BibTeX} ${Build}/${basename $@}
    6969        # Run again to finish citations
    7070        ${LaTeX} ${basename $@}.tex
     
    7272## Define the default recipes.
    7373
    74 ${Build} :
     74${Build}:
    7575        mkdir -p ${Build}
    7676
    77 ${BASE}.out.ps : | ${Build}
     77${BASE}.out.ps: ${Build}
    7878        ln -fs ${Build}/Paper.out.ps .
    7979
    80 WileyNJD-AMA.bst :
     80WileyNJD-AMA.bst:
    8181        ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst .
    8282
    83 %.tex : %.fig | ${Build}
     83%.tex : %.fig ${Build}
    8484        fig2dev -L eepic $< > ${Build}/$@
    8585
    86 %.ps : %.fig | ${Build}
     86%.ps : %.fig ${Build}
    8787        fig2dev -L ps $< > ${Build}/$@
    8888
    89 %.pstex : %.fig | ${Build}
     89%.pstex : %.fig ${Build}
    9090        fig2dev -L pstex $< > ${Build}/$@
    9191        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Paper.tex

    rb21c77a r97397a26  
    5656\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    5757\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
     58\newcommand{\R}[1]{\Textbf{#1}}
     59\newcommand{\B}[1]{{\Textbf[blue]{#1}}}
     60\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    5861\newcommand{\uC}{$\mu$\CC}
    59 \newcommand{\TODO}[1]{{\Textbf{#1}}}
     62\newcommand{\cit}{\textsuperscript{[Citation Needed]}\xspace}
     63\newcommand{\TODO}{{\Textbf{TODO}}}
    6064
    6165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    254258\section{Introduction}
    255259
    256 This paper provides a minimal concurrency \newterm{Application Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
     260This paper provides a minimal concurrency \newterm{Abstract Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
    257261While the simplest concurrency system is a thread and a lock, this low-level approach is hard to master.
    258262An easier approach for programmers is to support higher-level constructs as the basis of concurrency.
     
    271275Hence, there are two problems to be solved: concurrency and parallelism.
    272276While these two concepts are often combined, they are distinct, requiring different tools~\cite[\S~2]{Buhr05a}.
    273 Concurrency tools handle mutual exclusion and synchronization, while parallelism tools handle performance, cost, and resource utilization.
     277Concurrency tools handle synchronization and mutual exclusion, while parallelism tools handle performance, cost and resource utilization.
    274278
    275279The proposed concurrency API is implemented in a dialect of C, called \CFA.
     
    282286Extended versions and explanation of the following code examples are available at the \CFA website~\cite{Cforall} or in Moss~\etal~\cite{Moss18}.
    283287
    284 \CFA is a non-object-oriented extension of ISO-C, and hence, supports all C paradigms.
     288\CFA is an extension of ISO-C, and hence, supports all C paradigms.
    285289%It is a non-object-oriented system-language, meaning most of the major abstractions have either no runtime overhead or can be opted out easily.
    286 Like C, the building blocks of \CFA are structures and routines.
     290Like C, the basics of \CFA revolve around structures and functions.
    287291Virtually all of the code generated by the \CFA translator respects C memory layouts and calling conventions.
    288292While \CFA is not an object-oriented language, lacking the concept of a receiver (\eg @this@) and nominal inheritance-relationships, C does have a notion of objects: ``region of data storage in the execution environment, the contents of which can represent values''~\cite[3.15]{C11}.
     
    296300int x = 1, y = 2, z = 3;
    297301int * p1 = &x, ** p2 = &p1,  *** p3 = &p2,      $\C{// pointers to x}$
    298     `&` r1 = x,   `&&` r2 = r1,   `&&&` r3 = r2;        $\C{// references to x}$
     302        `&` r1 = x,  `&&` r2 = r1,  `&&&` r3 = r2;      $\C{// references to x}$
    299303int * p4 = &z, `&` r4 = z;
    300304
     
    345349        'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
    346350\end{cfa}
    347 and may appear as the body of a routine or nested within a routine body.
     351and may appear as the body of a function or nested within a function body.
    348352Each expression in the expression-list provides a type and object.
    349353The type must be an aggregate type.
     
    356360
    357361\CFA maximizes the ability to reuse names via overloading to aggressively address the naming problem.
    358 Both variables and routines may be overloaded, where selection is based on types, and number of returns (as in Ada~\cite{Ada}) and arguments.
     362Both variables and functions may be overloaded, where selection is based on types, and number of returns (as in Ada~\cite{Ada}) and arguments.
    359363\begin{cquote}
    360364\vspace*{-\baselineskip}%???
     
    411415\end{cquote}
    412416Overloading is important for \CFA concurrency since the runtime system relies on creating different types to represent concurrency objects.
    413 Therefore, overloading eliminates long prefixes and other naming conventions to prevent name clashes.
    414 As seen in Section~\ref{basics}, routine @main@ is heavily overloaded.
    415 For example, variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
     417Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions to prevent name clashes.
     418As seen in Section~\ref{basics}, function @main@ is heavily overloaded.
     419
     420Variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
    416421\begin{cfa}
    417422struct S { int `i`; int j; double m; } s;
     
    427432}
    428433\end{cfa}
    429 For parallel semantics, both @s.i@ and @t.i@ are visible with the same type, so only @i@ is ambiguous without qualification.
     434For parallel semantics, both @s.i@ and @t.i@ are visible the same type, so only @i@ is ambiguous without qualification.
    430435
    431436
     
    433438
    434439Overloading also extends to operators.
    435 Operator-overloading syntax creates a routine name with an operator symbol and question marks for the operands:
     440Operator-overloading syntax names a routine with the operator symbol and question marks for the operands:
    436441\begin{cquote}
    437442\lstDeleteShortInline@%
     
    467472\end{cquote}
    468473While concurrency does not use operator overloading directly, it provides an introduction for the syntax of constructors.
     474
     475
     476\subsection{Parametric Polymorphism}
     477\label{s:ParametricPolymorphism}
     478
     479The signature feature of \CFA is parametric-polymorphic functions~\cite{} with functions generalized using a @forall@ clause (giving the language its name), which allow separately compiled routines to support generic usage over multiple types.
     480For example, the following sum function works for any type that supports construction from 0 and addition:
     481\begin{cfa}
     482forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
     483T sum( T a[$\,$], size_t size ) {
     484        `T` total = { `0` };                                    $\C{// initialize by 0 constructor}$
     485        for ( size_t i = 0; i < size; i += 1 )
     486                total = total `+` a[i];                         $\C{// select appropriate +}$
     487        return total;
     488}
     489S sa[5];
     490int i = sum( sa, 5 );                                           $\C{// use S's 0 construction and +}$
     491\end{cfa}
     492
     493\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:
     494\begin{cfa}
     495trait `sumable`( otype T ) {
     496        void `?{}`( T &, zero_t );                              $\C{// 0 literal constructor}$
     497        T `?+?`( T, T );                                                $\C{// assortment of additions}$
     498        T ?+=?( T &, T );
     499        T ++?( T & );
     500        T ?++( T & );
     501};
     502forall( otype T `| sumable( T )` )                      $\C{// use trait}$
     503T sum( T a[$\,$], size_t size );
     504\end{cfa}
     505
     506Assertions can be @otype@ or @dtype@.
     507@otype@ refers to a ``complete'' object, \ie an object has a size, default constructor, copy constructor, destructor and an assignment operator.
     508@dtype@ only guarantees an object has a size and alignment.
     509
     510Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
     511\begin{cfa}
     512forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
     513int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
     514double * dp = alloc();
     515struct S {...} * sp = alloc();
     516\end{cfa}
     517where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    469518
    470519
     
    495544\CFA also provides @new@ and @delete@, which behave like @malloc@ and @free@, in addition to constructing and destructing objects:
    496545\begin{cfa}
    497 {
    498         ... struct S s = {10}; ...                              $\C{// allocation, call constructor}$
     546{       struct S s = {10};                                              $\C{// allocation, call constructor}$
     547        ...
    499548}                                                                                       $\C{// deallocation, call destructor}$
    500549struct S * s = new();                                           $\C{// allocation, call constructor}$
     
    502551delete( s );                                                            $\C{// deallocation, call destructor}$
    503552\end{cfa}
    504 \CFA concurrency uses object lifetime as a means of mutual exclusion and/or synchronization.
    505 
    506 
    507 \subsection{Parametric Polymorphism}
    508 \label{s:ParametricPolymorphism}
    509 
    510 The signature feature of \CFA is parametric-polymorphic routines~\cite{} with routines generalized using a @forall@ clause (giving the language its name), which allow separately compiled routines to support generic usage over multiple types.
    511 For example, the following sum routine works for any type that supports construction from 0 and addition:
    512 \begin{cfa}
    513 forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
    514 T sum( T a[$\,$], size_t size ) {
    515         `T` total = { `0` };                                    $\C{// initialize by 0 constructor}$
    516         for ( size_t i = 0; i < size; i += 1 )
    517                 total = total `+` a[i];                         $\C{// select appropriate +}$
    518         return total;
    519 }
    520 S sa[5];
    521 int i = sum( sa, 5 );                                           $\C{// use S's 0 construction and +}$
    522 \end{cfa}
    523 The builtin type @zero_t@ (and @one_t@) overload constant 0 (and 1) for a new types, where both 0 and 1 have special meaning in C.
    524 
    525 \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 routine declaration:
    526 \begin{cfa}
    527 trait `sumable`( otype T ) {
    528         void `?{}`( T &, zero_t );                              $\C{// 0 literal constructor}$
    529         T `?+?`( T, T );                                                $\C{// assortment of additions}$
    530         T ?+=?( T &, T );
    531         T ++?( T & );
    532         T ?++( T & );
    533 };
    534 forall( otype T `| sumable( T )` )                      $\C{// use trait}$
    535 T sum( T a[$\,$], size_t size );
    536 \end{cfa}
    537 
    538 Assertions can be @otype@ or @dtype@.
    539 @otype@ refers to a ``complete'' object, \ie an object has a size, default constructor, copy constructor, destructor and an assignment operator.
    540 @dtype@ only guarantees an object has a size and alignment.
    541 
    542 Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
    543 \begin{cfa}
    544 forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
    545 int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
    546 double * dp = alloc();
    547 struct S {...} * sp = alloc();
    548 \end{cfa}
    549 where the return type supplies the type/size of the allocation, which is impossible in most type systems.
     553\CFA concurrency uses object lifetime as a means of synchronization and/or mutual exclusion.
    550554
    551555
     
    580584\subsection{\protect\CFA's Thread Building Blocks}
    581585
    582 An important missing feature in C is threading\footnote{While the C11 standard defines a \protect\lstinline@threads.h@ header, it is minimal and defined as optional.
     586An important missing feature in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
    583587As such, library support for threading is far from widespread.
    584 At the time of writing the paper, neither \protect\lstinline@gcc@ nor \protect\lstinline@clang@ support \protect\lstinline@threads.h@ in their standard libraries.}.
    585 In modern programming languages, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
     588At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
     589On modern architectures, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
    586590As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages.
    587591Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
     
    621625\newbox\myboxA
    622626\begin{lrbox}{\myboxA}
    623 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     627\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    624628`int f1, f2, state = 1;`   // single global variables
    625629int fib() {
     
    638642        }
    639643}
    640 \end{cfa}
     644\end{lstlisting}
    641645\end{lrbox}
    642646
    643647\newbox\myboxB
    644648\begin{lrbox}{\myboxB}
    645 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     649\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    646650#define FIB_INIT `{ 0, 1 }`
    647651typedef struct { int f2, f1; } Fib;
     
    660664        }
    661665}
    662 \end{cfa}
     666\end{lstlisting}
    663667\end{lrbox}
    664668
     
    673677\newbox\myboxA
    674678\begin{lrbox}{\myboxA}
    675 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     679\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    676680`coroutine` Fib { int fn; };
    677681void main( Fib & fib ) with( fib ) {
     
    693697        }
    694698}
    695 \end{cfa}
     699\end{lstlisting}
    696700\end{lrbox}
    697701\newbox\myboxB
    698702\begin{lrbox}{\myboxB}
    699 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     703\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    700704`coroutine` Fib { int ret; };
    701705void main( Fib & f ) with( fib ) {
     
    717721
    718722
    719 \end{cfa}
     723\end{lstlisting}
    720724\end{lrbox}
    721725\subfloat[3 States, internal variables]{\label{f:Coroutine3States}\usebox\myboxA}
     
    727731
    728732Using a coroutine, it is possible to express the Fibonacci formula directly without any of the C problems.
    729 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type, @`coroutine` Fib { int fn; }@, which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface routines, \eg @next@.
     733Figure~\ref{f:Coroutine3States} creates a @coroutine@ type:
     734\begin{cfa}
     735`coroutine` Fib { int fn; };
     736\end{cfa}
     737which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface functions, @next@.
    730738Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the (overloaded) coroutine main.
    731 The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code has the three suspend points, representing the three states in the Fibonacci formula, to context switch back to the caller's @resume@.
    732 The interface routine @next@, takes a Fibonacci instance and context switches to it using @resume@;
     739The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code has the three suspend points, representing the three states in the Fibonacci formula, to context switch back to the caller's resume.
     740The interface function, @next@, takes a Fibonacci instance and context switches to it using @resume@;
    733741on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
    734742The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack;
     
    761769\newbox\myboxA
    762770\begin{lrbox}{\myboxA}
    763 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     771\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    764772`coroutine` Format {
    765773        char ch;   // used for communication
     
    793801        }
    794802}
    795 \end{cfa}
     803\end{lstlisting}
    796804\end{lrbox}
    797805
    798806\newbox\myboxB
    799807\begin{lrbox}{\myboxB}
    800 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     808\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    801809struct Format {
    802810        char ch;
     
    830838        format( &fmt );
    831839}
    832 \end{cfa}
     840\end{lstlisting}
    833841\end{lrbox}
    834842\subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
     
    839847\end{figure}
    840848
    841 The previous examples are \newterm{asymmetric (semi) coroutine}s because one coroutine always calls a resuming routine for another coroutine, and the resumed coroutine always suspends back to its last resumer, similar to call/return for normal routines.
    842 However,@resume@/@suspend@ context switch to existing stack-frames rather than create new ones so there is no stack growth.
    843 \newterm{Symmetric (full) coroutine}s have a coroutine call a resuming routine for another coroutine, which eventually forms a resuming-call cycle.
     849The previous examples are \newterm{asymmetric (semi) coroutine}s because one coroutine always calls a resuming function for another coroutine, and the resumed coroutine always suspends back to its last resumer, similar to call/return for normal functions.
     850However, there is no stack growth because @resume@/@suspend@ context switch to existing stack-frames rather than create new ones.
     851\newterm{Symmetric (full) coroutine}s have a coroutine call a resuming function for another coroutine, which eventually forms a resuming-call cycle.
    844852(The trivial cycle is a coroutine resuming itself.)
    845853This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch.
     
    923931Figure~\ref{f:ProdCons} shows a producer/consumer symmetric-coroutine performing bi-directional communication.
    924932Since the solution involves a full-coroutining cycle, the program main creates one coroutine in isolation, passes this coroutine to its partner, and closes the cycle at the call to @start@.
    925 The @start@ routine communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
     933The @start@ function communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
    926934Then the @resume@ to @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it.
    927935@prod@'s coroutine main starts, creates local variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random values, calling the consumer to deliver the values, and printing the status returned from the consumer.
     
    929937The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    930938For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine.
    931 The consumer iterates until the @done@ flag is set, prints the values delivered by the producer, increments status, and calls back to the producer via @payment@, and on return from @payment@, prints the receipt from the producer and increments @money@ (inflation).
     939The consumer iterates until the @done@ flag is set, prints, increments status, and calls back to the producer via @payment@, and on return from @payment@, prints the receipt from the producer and increments @money@ (inflation).
    932940The call from the consumer to the @payment@ introduces the cycle between producer and consumer.
    933941When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed.
     
    959967\end{cfa}
    960968and the programming language (and possibly its tool set, \eg debugger) may need to understand @baseCoroutine@ because of the stack.
    961 Furthermore, the execution of constructs/destructors is in the wrong order for certain operations.
    962 For example, for threads if the thread is implicitly started, it must start \emph{after} all constructors, because the thread relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.
     969Furthermore, the execution of constructs/destructors is in the wrong order for certain operations, \eg for threads;
     970\eg, if the thread is implicitly started, it must start \emph{after} all constructors, because the thread relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.
    963971
    964972An alternatively is composition:
     
    972980However, there is nothing preventing wrong placement or multiple declarations.
    973981
    974 For coroutines as for threads, many implementations are based on routine pointers or routine objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
     982For coroutines as for threads, many implementations are based on routine pointers or function objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
    975983For example, Boost implements coroutines in terms of four functor object-types:
    976984\begin{cfa}
     
    980988symmetric_coroutine<>::yield_type
    981989\end{cfa}
    982 Similarly, the canonical threading paradigm is often based on routine pointers, \eg @pthreads@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
     990Similarly, the canonical threading paradigm is often based on function pointers, \eg @pthread@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
    983991However, the generic thread-handle (identifier) is limited (few operations), unless it is wrapped in a custom type.
    984992\begin{cfa}
     
    9941002\end{cfa}
    9951003Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda-based coroutines adds very little.
    996 
    997 Note, the type @coroutine_t@ must be an abstract handle to the coroutine, because the coroutine descriptor and its stack are non-copyable.
    998 Copying the coroutine descriptor results in copies being out of date with the current state of the stack.
    999 Correspondingly, copying the stack results is copies being out of date with the coroutine descriptor, and pointers in the stack being out of date to data on the stack.
    1000 (There is no mechanism in C to find all stack-specific pointers and update them as part of a copy.)
    10011004
    10021005The selected approach is to use language support by introducing a new kind of aggregate (structure):
     
    10111014Furthermore, implementing coroutines without language supports also displays the power of a programming language.
    10121015While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed without using the language support.
    1013 The reserved keyword simply eases use for the common cases.
    1014 
    1015 Part of the mechanism to generalize coroutines is using a \CFA trait, which defines a coroutine as anything satisfying the trait @is_coroutine@, and this trait is used to restrict coroutine-manipulation routines:
    1016 \begin{cfa}
    1017 trait is_coroutine( `dtype` T ) {
    1018         void main( T & );
    1019         coroutine_desc * get_coroutine( T & );
     1016The reserved keyword eases use for the common cases.
     1017
     1018Part of the mechanism to generalize coroutines is using a \CFA trait, which defines a coroutine as anything satisfying the trait @is_coroutine@, and this trait is used to restrict coroutine-manipulation functions:
     1019\begin{cfa}
     1020trait is_coroutine( dtype T ) {
     1021      void main( T & this );
     1022      coroutine_desc * get_coroutine( T & this );
    10201023};
    1021 forall( `dtype` T | is_coroutine(T) ) void suspend( T & );
    1022 forall( `dtype` T | is_coroutine(T) ) void resume( T & );
    1023 \end{cfa}
    1024 The @dtype@ property of the trait ensures the coroutine descriptor is non-copyable, so all coroutines must be passed by reference (pointer).
    1025 The routine definitions ensures there is a statically-typed @main@ routine that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read) the currently executing coroutine handle.
    1026 The @main@ routine has no return value or additional parameters because the coroutine type allows an arbitrary number of interface routines with corresponding arbitrary typed input/output values versus fixed ones.
    1027 The generic routines @suspend@ and @resume@ can be redefined, but any object passed to them is a coroutine since it must satisfy the @is_coroutine@ trait to compile.
    1028 The advantage of this approach is that users can easily create different types of coroutines, \eg changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ routine, and possibly redefining @suspend@ and @resume@.
     1024forall( dtype T | is_coroutine(T) ) void get_coroutine( T & );
     1025forall( dtype T | is_coroutine(T) ) void suspend( T & );
     1026forall( dtype T | is_coroutine(T) ) void resume( T & );
     1027\end{cfa}
     1028This definition ensures there is a statically-typed @main@ function that is the starting point (first stack frame) of a coroutine.
     1029No return value or additional parameters are necessary for this function, because the coroutine type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values.
     1030As well, any object passed to @suspend@ and @resume@ is a coroutine since it must satisfy the @is_coroutine@ trait to compile.
     1031The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ routine.
    10291032The \CFA keyword @coroutine@ implicitly implements the getter and forward declarations required for implementing the coroutine main:
    10301033\begin{cquote}
     
    10361039};
    10371040\end{cfa}
    1038 &
    1039 {\Large $\Rightarrow$}
    1040 &
     1041& {\Large $\Rightarrow$} &
    10411042\begin{tabular}{@{}ccc@{}}
    10421043\begin{cfa}
     
    10721073Like coroutines and for the same design reasons, the selected approach for user threads is to use language support by introducing a new kind of aggregate (structure) and a \CFA trait:
    10731074\begin{cquote}
    1074 \begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
     1075\begin{tabular}{@{}c@{\hspace{2\parindentlnth}}c@{}}
    10751076\begin{cfa}
    10761077thread myThread {
     
    10821083&
    10831084\begin{cfa}
    1084 trait is_thread( `dtype` T ) {
    1085       void main( T & );
    1086       thread_desc * get_thread( T & );
    1087       void ^?{}( T & `mutex` );
     1085trait is_thread( dtype T ) {
     1086      void main( T & this );
     1087      thread_desc * get_thread( T & this );
     1088      void ^?{}( T & `mutex` this );
    10881089};
    10891090\end{cfa}
     
    10911092\end{cquote}
    10921093(The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitors}.)
    1093 Like a coroutine, the statically-typed @main@ routine is the starting point (first stack frame) of a user thread.
     1094Like a coroutine, the statically-typed @main@ function is the starting point (first stack frame) of a user thread.
    10941095The difference is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates an instance of @main@;
    10951096whereas, a user thread receives its own thread from the runtime system, which starts in @main@ as some point after the thread constructor is run.\footnote{
    1096 The \lstinline@main@ routine is already a special routine in C, \ie where the program's initial thread begins, so it is a natural extension of this semantics to use overloading to declare \lstinline@main@s for user coroutines and threads.}
    1097 No return value or additional parameters are necessary for this routine because the task type allows an arbitrary number of interface routines with corresponding arbitrary typed input/output values.
     1097The \lstinline@main@ function is already a special routine in C (where the program begins), so it is a natural extension of the semantics to use overloading to declare mains for different coroutines/threads (the normal main being the main of the initial thread).}
     1098No return value or additional parameters are necessary for this function, because the task type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values.
    10981099
    10991100\begin{comment} % put in appendix with coroutine version ???
     
    11081109
    11091110In this example, threads of type @foo@ start execution in the @void main(foo &)@ routine, which prints @"Hello World!".@ While this paper encourages this approach to enforce strongly typed programming, users may prefer to use the routine-based thread semantics for the sake of simplicity.
    1110 With the static semantics it is trivial to write a thread type that takes a routine pointer as a parameter and executes it on its stack asynchronously.
    1111 \begin{cfa}
    1112 typedef void (*voidRtn)(int);
    1113 
    1114 thread RtnRunner {
    1115         voidRtn func;
     1111With the static semantics it is trivial to write a thread type that takes a function pointer as a parameter and executes it on its stack asynchronously.
     1112\begin{cfa}
     1113typedef void (*voidFunc)(int);
     1114
     1115thread FuncRunner {
     1116        voidFunc func;
    11161117        int arg;
    11171118};
    11181119
    1119 void ?{}(RtnRunner & this, voidRtn inRtn, int arg) {
    1120         this.func = inRtn;
     1120void ?{}(FuncRunner & this, voidFunc inFunc, int arg) {
     1121        this.func = inFunc;
    11211122        this.arg  = arg;
    11221123}
    11231124
    1124 void main(RtnRunner & this) {
    1125         // thread starts here and runs the routine
     1125void main(FuncRunner & this) {
     1126        // thread starts here and runs the function
    11261127        this.func( this.arg );
    11271128}
     
    11321133
    11331134int main() {
    1134         RtnRunner f = {hello, 42};
     1135        FuncRunner f = {hello, 42};
    11351136        return 0?
    11361137}
    11371138\end{cfa}
    1138 A consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \textbf{API}.
     1139A consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \textbf{api}.
    11391140\end{comment}
    11401141
     
    11851186void main( Adder & adder ) with( adder ) {
    11861187    subtotal = 0;
    1187     for ( int c = 0; c < cols; c += 1 ) { subtotal += row[c]; }
     1188    for ( int c = 0; c < cols; c += 1 ) {
     1189                subtotal += row[c];
     1190    }
    11881191}
    11891192int main() {
     
    12071210
    12081211
    1209 \section{Mutual Exclusion / Synchronization}
     1212\section{Synchronization / Mutual Exclusion}
    12101213
    12111214Uncontrolled non-deterministic execution is meaningless.
    1212 To reestablish meaningful execution requires mechanisms to reintroduce determinism, \ie restrict non-determinism, called mutual exclusion and synchronization, where mutual exclusion is an access-control mechanism on data shared by threads, and synchronization is a timing relationship among threads~\cite[\S~4]{Buhr05a}.
    1213 Since many deterministic challenges appear with the use of mutable shared state, some languages/libraries disallow it, \eg Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka~\cite{Akka} (Scala).
    1214 In these paradigms, interaction among concurrent objects is performed by stateless message-passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts, \eg channels~\cite{CSP,Go}.
    1215 However, in call/return-based languages, these approaches force a clear distinction, \ie introduce a new programming paradigm, between regular and concurrent computation, \eg routine call versus message passing.
    1216 Hence, a programmer must learn and manipulate two sets of design patterns.
     1215To reestablish meaningful execution requires mechanisms to reintroduce determinism (control non-determinism), called synchronization and mutual exclusion, where synchronization is a timing relationship among threads and mutual exclusion is an access-control mechanism on data shared by threads.
     1216Since many deterministic challenges appear with the use of mutable shared state, some languages/libraries disallow it (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka~\cite{Akka} (Scala)).
     1217In these paradigms, interaction among concurrent objects is performed by stateless message-passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (\eg channels~\cite{CSP,Go}).
     1218However, in call/return-based languages, these approaches force a clear distinction (\ie introduce a new programming paradigm) between non-concurrent and concurrent computation (\ie function call versus message passing).
     1219This distinction means a programmers needs to learn two sets of design patterns.
    12171220While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account.
    12181221In contrast, approaches based on statefull models more closely resemble the standard call/return programming-model, resulting in a single programming paradigm.
    12191222
    1220 At the lowest level, concurrent control is implemented by atomic operations, upon which different kinds of locks mechanism are constructed, \eg semaphores~\cite{Dijkstra68b}, barriers, and path expressions~\cite{Campbell74}.
     1223At the lowest level, concurrent control is implemented as atomic operations, upon which different kinds of locks mechanism are constructed, \eg semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}.
    12211224However, for productivity it is always desirable to use the highest-level construct that provides the necessary efficiency~\cite{Hochstein05}.
    1222 A newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}.
     1225A newer approach is transactional memory~\cite{Herlihy93}.
    12231226While this approach is pursued in hardware~\cite{Nakaike15} and system languages, like \CC~\cite{Cpp-Transactions}, the performance and feature set is still too restrictive to be the main concurrency paradigm for system languages, which is why it was rejected as the core paradigm for concurrency in \CFA.
    12241227
    1225 One of the most natural, elegant, and efficient mechanisms for mutual exclusion and synchronization for shared-memory systems is the \emph{monitor}.
    1226 First proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}, many concurrent programming-languages provide monitors as an explicit language construct: \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}.
    1227 In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as mutex locks or semaphores to simulate monitors.
    1228 For these reasons, \CFA selected monitors as the core high-level concurrency-construct, upon which higher-level approaches can be easily constructed.
     1228One of the most natural, elegant, and efficient mechanisms for synchronization and mutual exclusion for shared-memory systems is the \emph{monitor}.
     1229Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}.
     1230Many programming languages -- \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java} -- provide monitors as explicit language constructs.
     1231In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors.
     1232For these reasons, this project proposes monitors as the core concurrency construct, upon which even higher-level approaches can be easily constructed..
    12291233
    12301234
     
    12321236
    12331237A group of instructions manipulating a specific instance of shared data that must be performed atomically is called an (individual) \newterm{critical-section}~\cite{Dijkstra65}.
    1234 The generalization is called a \newterm{group critical-section}~\cite{Joung00}, where multiple tasks with the same session may use the resource simultaneously, but different sessions may not use the resource simultaneously.
     1238A generalization is a \newterm{group critical-section}~\cite{Joung00}, where multiple tasks with the same session may use the resource simultaneously, but different sessions may not use the resource simultaneously.
    12351239The readers/writer problem~\cite{Courtois71} is an instance of a group critical-section, where readers have the same session and all writers have a unique session.
    1236 \newterm{Mutual exclusion} enforces that the correct kind and number of threads are using a critical section.
     1240\newterm{Mutual exclusion} enforces the correction number of threads are using a critical section at the same time.
    12371241
    12381242However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use.
    12391243Methods range from low-level locks, which are fast and flexible but require significant attention for correctness, to higher-level concurrency techniques, which sacrifice some performance to improve ease of use.
    1240 Ease of use comes by either guaranteeing some problems cannot occur, \eg deadlock free, or by offering a more explicit coupling between shared data and critical section.
    1241 For example, the \CC @std::atomic<T>@ offers an easy way to express mutual-exclusion on a restricted set of operations, \eg reading/writing, for numerical types.
    1242 However, a significant challenge with locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
    1243 Easing composability is another feature higher-level mutual-exclusion mechanisms can offer.
     1244Ease of use comes by either guaranteeing some problems cannot occur (\eg deadlock free), or by offering a more explicit coupling between shared data and critical section.
     1245For example, the \CC @std::atomic<T>@ offers an easy way to express mutual-exclusion on a restricted set of operations (\eg reading/writing large types atomically).
     1246However, a significant challenge with (low-level) locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
     1247Easing composability is another feature higher-level mutual-exclusion mechanisms offer.
    12441248
    12451249
     
    12471251
    12481252Synchronization enforces relative ordering of execution, and synchronization tools provide numerous mechanisms to establish these timing relationships.
    1249 Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use;
    1250 higher-level mechanisms often simplify usage by adding better coupling between synchronization and data, \eg message passing, or offering a simpler solution to otherwise involved challenges, \eg barrier lock.
    1251 Often synchronization is used to order access to a critical section, \eg ensuring a reader thread is the next kind of thread to enter a critical section.
    1252 If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, that reader has \newterm{barged}.
    1253 Barging can result in staleness/freshness problems, where a reader barges ahead of a writer and reads temporally stale data, or a writer barges ahead of another writer overwriting data with a fresh value preventing the previous value from ever being read (lost computation).
     1253Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use.
     1254Higher-level mechanisms often simplify usage by adding better coupling between synchronization and data (\eg message passing), or offering a simpler solution to otherwise involved challenges, \eg barrier lock.
     1255As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}.
     1256Often synchronization is used to order access to a critical section, \eg ensuring the next kind of thread to enter a critical section is a reader thread
     1257If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, the reader has \newterm{barged}.
     1258Barging can result in staleness/freshness problems, where a reader barges ahead of a write and reads temporally stale data, or a writer barges ahead of another writer overwriting data with a fresh value preventing the previous value from having an opportunity to be read.
    12541259Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
    1255 This challenge is often split into two different approaches: barging avoidance and barging prevention.
    1256 Algorithms that allow a barger, but divert it until later using current synchronization state (flags), are avoiding the barger;
    1257 algorithms that preclude a barger from entering during synchronization in the critical section prevent barging completely.
    1258 Techniques like baton-pass locks~\cite{Andrews89} between threads instead of unconditionally releasing locks is an example of barging prevention.
     1260This challenge is often split into two different approaches, barging avoidance and barging prevention.
     1261Algorithms that allow a barger but divert it until later are avoiding the barger, while algorithms that preclude a barger from entering during synchronization in the critical section prevent the barger completely.
     1262baton-pass locks~\cite{Andrews89} between threads instead of releasing the locks are said to be using barging prevention.
    12591263
    12601264
     
    12621266\label{s:Monitors}
    12631267
    1264 A \textbf{monitor} is a set of routines that ensure mutual exclusion when accessing shared state.
    1265 More precisely, a monitor is a programming technique that binds mutual exclusion to routine scope, as opposed to locks, where mutual-exclusion is defined by acquire/release calls, independent of lexical context (analogous to block and heap storage allocation).
    1266 The strong association with the call/return paradigm eases programmability, readability and maintainability, at a slight cost in flexibility and efficiency.
    1267 
    1268 Note, like coroutines/threads, both locks and monitors require an abstract handle to reference them, because at their core, both mechanisms are manipulating non-copyable shared-state.
    1269 Copying a lock is insecure because it is possible to copy an open lock and then use the open copy when the original lock is closed to simultaneously access the shared data.
    1270 Copying a monitor is secure because both the lock and shared data are copies, but copying the shared data is meaningless because it no longer represents a unique entity.
    1271 As for coroutines/tasks, a non-copyable (@dtype@) trait is used to capture this requirement, so all locks/monitors must be passed by reference (pointer).
    1272 \begin{cfa}
    1273 trait is_monitor( `dtype` T ) {
     1268A \textbf{monitor} is a set of routines that ensure mutual-exclusion when accessing shared state.
     1269More precisely, a monitor is a programming technique that associates mutual-exclusion to routine scopes, as opposed to mutex locks, where mutual-exclusion is defined by lock/release calls independently of any scoping of the calling routine.
     1270This strong association eases readability and maintainability, at the cost of flexibility.
     1271Note that both monitors and mutex locks, require an abstract handle to identify them.
     1272This concept is generally associated with object-oriented languages like Java~\cite{Java} or \uC~\cite{uC++book} but does not strictly require OO semantics.
     1273The only requirement is the ability to declare a handle to a shared object and a set of routines that act on it:
     1274\begin{cfa}
     1275typedef /*some monitor type*/ monitor;
     1276int f(monitor & m);
     1277
     1278int main() {
     1279        monitor m;  // Handle m
     1280        f(m);       // Routine using handle
     1281}
     1282\end{cfa}
     1283
     1284% ======================================================================
     1285% ======================================================================
     1286\subsection{Call Semantics} \label{call}
     1287% ======================================================================
     1288% ======================================================================
     1289The above monitor example displays some of the intrinsic characteristics.
     1290First, it is necessary to use pass-by-reference over pass-by-value for monitor routines.
     1291This semantics is important, because at their core, monitors are implicit mutual-exclusion objects (locks), and these objects cannot be copied.
     1292Therefore, monitors are non-copy-able objects (@dtype@).
     1293
     1294Another aspect to consider is when a monitor acquires its mutual exclusion.
     1295For example, a monitor may need to be passed through multiple helper routines that do not acquire the monitor mutual-exclusion on entry.
     1296Passthrough can occur for generic helper routines (@swap@, @sort@, \etc) or specific helper routines like the following to implement an atomic counter:
     1297
     1298\begin{cfa}
     1299monitor counter_t { /*...see section $\ref{data}$...*/ };
     1300
     1301void ?{}(counter_t & nomutex this); // constructor
     1302size_t ++?(counter_t & mutex this); // increment
     1303
     1304// need for mutex is platform dependent
     1305void ?{}(size_t * this, counter_t & mutex cnt); // conversion
     1306\end{cfa}
     1307This counter is used as follows:
     1308\begin{center}
     1309\begin{tabular}{c @{\hskip 0.35in} c @{\hskip 0.35in} c}
     1310\begin{cfa}
     1311// shared counter
     1312counter_t cnt1, cnt2;
     1313
     1314// multiple threads access counter
     1315thread 1 : cnt1++; cnt2++;
     1316thread 2 : cnt1++; cnt2++;
     1317thread 3 : cnt1++; cnt2++;
     1318        ...
     1319thread N : cnt1++; cnt2++;
     1320\end{cfa}
     1321\end{tabular}
     1322\end{center}
     1323Notice how the counter is used without any explicit synchronization and yet supports thread-safe semantics for both reading and writing, which is similar in usage to the \CC template @std::atomic@.
     1324
     1325Here, the constructor (@?{}@) uses the @nomutex@ keyword to signify that it does not acquire the monitor mutual-exclusion when constructing.
     1326This semantics is because an object not yet constructed should never be shared and therefore does not require mutual exclusion.
     1327Furthermore, it allows the implementation greater freedom when it initializes the monitor locking.
     1328The prefix increment operator uses @mutex@ to protect the incrementing process from race conditions.
     1329Finally, there is a conversion operator from @counter_t@ to @size_t@.
     1330This conversion may or may not require the @mutex@ keyword depending on whether or not reading a @size_t@ is an atomic operation.
     1331
     1332For maximum usability, monitors use \textbf{multi-acq} semantics, which means a single thread can acquire the same monitor multiple times without deadlock.
     1333For example, listing \ref{fig:search} uses recursion and \textbf{multi-acq} to print values inside a binary tree.
     1334\begin{figure}
     1335\begin{cfa}[caption={Recursive printing algorithm using \textbf{multi-acq}.},label={fig:search}]
     1336monitor printer { ... };
     1337struct tree {
     1338        tree * left, right;
     1339        char * value;
     1340};
     1341void print(printer & mutex p, char * v);
     1342
     1343void print(printer & mutex p, tree * t) {
     1344        print(p, t->value);
     1345        print(p, t->left );
     1346        print(p, t->right);
     1347}
     1348\end{cfa}
     1349\end{figure}
     1350
     1351Having both @mutex@ and @nomutex@ keywords can be redundant, depending on the meaning of a routine having neither of these keywords.
     1352For example, it is reasonable that it should default to the safest option (@mutex@) when given a routine without qualifiers @void foo(counter_t & this)@, whereas assuming @nomutex@ is unsafe and may cause subtle errors.
     1353On the other hand, @nomutex@ is the ``normal'' parameter behaviour, it effectively states explicitly that ``this routine is not special''.
     1354Another alternative is making exactly one of these keywords mandatory, which provides the same semantics but without the ambiguity of supporting routines with neither keyword.
     1355Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing.
     1356While there are several benefits to mandatory keywords, they do bring a few challenges.
     1357Mandatory keywords in \CFA would imply that the compiler must know without doubt whether or not a parameter is a monitor or not.
     1358Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred.
     1359For this reason, \CFA only has the @mutex@ keyword and uses no keyword to mean @nomutex@.
     1360
     1361The next semantic decision is to establish when @mutex@ may be used as a type qualifier.
     1362Consider the following declarations:
     1363\begin{cfa}
     1364int f1(monitor & mutex m);
     1365int f2(const monitor & mutex m);
     1366int f3(monitor ** mutex m);
     1367int f4(monitor * mutex m []);
     1368int f5(graph(monitor *) & mutex m);
     1369\end{cfa}
     1370The problem is to identify which object(s) should be acquired.
     1371Furthermore, each object needs to be acquired only once.
     1372In the case of simple routines like @f1@ and @f2@ it is easy to identify an exhaustive list of objects to acquire on entry.
     1373Adding indirections (@f3@) still allows the compiler and programmer to identify which object is acquired.
     1374However, adding in arrays (@f4@) makes it much harder.
     1375Array lengths are not necessarily known in C, and even then, making sure objects are only acquired once becomes none-trivial.
     1376This problem can be extended to absurd limits like @f5@, which uses a graph of monitors.
     1377To make the issue tractable, this project imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with at most one level of indirection (ignoring potential qualifiers).
     1378Also note that while routine @f3@ can be supported, meaning that monitor @**m@ is acquired, passing an array to this routine would be type-safe and yet result in undefined behaviour because only the first element of the array is acquired.
     1379However, this ambiguity is part of the C type-system with respects to arrays.
     1380For this reason, @mutex@ is disallowed in the context where arrays may be passed:
     1381\begin{cfa}
     1382int f1(monitor & mutex m);    // Okay : recommended case
     1383int f2(monitor * mutex m);    // Not Okay : Could be an array
     1384int f3(monitor mutex m []);  // Not Okay : Array of unknown length
     1385int f4(monitor ** mutex m);   // Not Okay : Could be an array
     1386int f5(monitor * mutex m []); // Not Okay : Array of unknown length
     1387\end{cfa}
     1388Note that not all array functions are actually distinct in the type system.
     1389However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
     1390
     1391Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion of the receiver object, \CFA uses an explicit mechanism to specify the object that acquires mutual-exclusion.
     1392A consequence of this approach is that it extends naturally to multi-monitor calls.
     1393\begin{cfa}
     1394int f(MonitorA & mutex a, MonitorB & mutex b);
     1395
     1396MonitorA a;
     1397MonitorB b;
     1398f(a,b);
     1399\end{cfa}
     1400While OO monitors could be extended with a mutex qualifier for multiple-monitor calls, no example of this feature could be found.
     1401The capability to acquire multiple locks before entering a critical section is called \emph{\textbf{bulk-acq}}.
     1402In practice, writing multi-locking routines that do not lead to deadlocks is tricky.
     1403Having language support for such a feature is therefore a significant asset for \CFA.
     1404In the case presented above, \CFA guarantees that the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
     1405This consistent ordering means acquiring multiple monitors is safe from deadlock when using \textbf{bulk-acq}.
     1406However, users can still force the acquiring order.
     1407For example, notice which routines use @mutex@/@nomutex@ and how this affects acquiring order:
     1408\begin{cfa}
     1409void foo(A& mutex a, B& mutex b) { // acquire a & b
     1410        ...
     1411}
     1412
     1413void bar(A& mutex a, B& /*nomutex*/ b) { // acquire a
     1414        ... foo(a, b); ... // acquire b
     1415}
     1416
     1417void baz(A& /*nomutex*/ a, B& mutex b) { // acquire b
     1418        ... foo(a, b); ... // acquire a
     1419}
     1420\end{cfa}
     1421The \textbf{multi-acq} monitor lock allows a monitor lock to be acquired by both @bar@ or @baz@ and acquired again in @foo@.
     1422In the calls to @bar@ and @baz@ the monitors are acquired in opposite order.
     1423
     1424However, such use leads to lock acquiring order problems.
     1425In the example above, the user uses implicit ordering in the case of function @foo@ but explicit ordering in the case of @bar@ and @baz@.
     1426This subtle difference means that calling these routines concurrently may lead to deadlock and is therefore undefined behaviour.
     1427As shown~\cite{Lister77}, solving this problem requires:
     1428\begin{enumerate}
     1429        \item Dynamically tracking the monitor-call order.
     1430        \item Implement rollback semantics.
     1431\end{enumerate}
     1432While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is still prohibitively complex~\cite{Dice10}.
     1433In \CFA, users simply need to be careful when acquiring multiple monitors at the same time or only use \textbf{bulk-acq} of all the monitors.
     1434While \CFA provides only a partial solution, most systems provide no solution and the \CFA partial solution handles many useful cases.
     1435
     1436For example, \textbf{multi-acq} and \textbf{bulk-acq} can be used together in interesting ways:
     1437\begin{cfa}
     1438monitor bank { ... };
     1439
     1440void deposit( bank & mutex b, int deposit );
     1441
     1442void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
     1443        deposit( mybank, -me2you );
     1444        deposit( yourbank, me2you );
     1445}
     1446\end{cfa}
     1447This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
     1448Without \textbf{multi-acq} and \textbf{bulk-acq}, the solution to this problem is much more involved and requires careful engineering.
     1449
     1450
     1451\subsection{\protect\lstinline|mutex| statement} \label{mutex-stmt}
     1452
     1453The call semantics discussed above have one software engineering issue: only a routine can acquire the mutual-exclusion of a set of monitor. \CFA offers the @mutex@ statement to work around the need for unnecessary names, avoiding a major software engineering problem~\cite{2FTwoHardThings}.
     1454Table \ref{f:mutex-stmt} shows an example of the @mutex@ statement, which introduces a new scope in which the mutual-exclusion of a set of monitor is acquired.
     1455Beyond naming, the @mutex@ statement has no semantic difference from a routine call with @mutex@ parameters.
     1456
     1457\begin{table}
     1458\begin{center}
     1459\begin{tabular}{|c|c|}
     1460function call & @mutex@ statement \\
     1461\hline
     1462\begin{cfa}[tabsize=3]
     1463monitor M {};
     1464void foo( M & mutex m1, M & mutex m2 ) {
     1465        // critical section
     1466}
     1467
     1468void bar( M & m1, M & m2 ) {
     1469        foo( m1, m2 );
     1470}
     1471\end{cfa}&\begin{cfa}[tabsize=3]
     1472monitor M {};
     1473void bar( M & m1, M & m2 ) {
     1474        mutex(m1, m2) {
     1475                // critical section
     1476        }
     1477}
     1478
     1479
     1480\end{cfa}
     1481\end{tabular}
     1482\end{center}
     1483\caption{Regular call semantics vs. \protect\lstinline|mutex| statement}
     1484\label{f:mutex-stmt}
     1485\end{table}
     1486
     1487% ======================================================================
     1488% ======================================================================
     1489\subsection{Data semantics} \label{data}
     1490% ======================================================================
     1491% ======================================================================
     1492Once the call semantics are established, the next step is to establish data semantics.
     1493Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data.
     1494This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection.
     1495For example, here is a complete version of the counter shown in section \ref{call}:
     1496\begin{cfa}
     1497monitor counter_t {
     1498        int value;
     1499};
     1500
     1501void ?{}(counter_t & this) {
     1502        this.cnt = 0;
     1503}
     1504
     1505int ?++(counter_t & mutex this) {
     1506        return ++this.value;
     1507}
     1508
     1509// need for mutex is platform dependent here
     1510void ?{}(int * this, counter_t & mutex cnt) {
     1511        *this = (int)cnt;
     1512}
     1513\end{cfa}
     1514
     1515Like threads and coroutines, monitors are defined in terms of traits with some additional language support in the form of the @monitor@ keyword.
     1516The monitor trait is:
     1517\begin{cfa}
     1518trait is_monitor(dtype T) {
    12741519        monitor_desc * get_monitor( T & );
    12751520        void ^?{}( T & mutex );
    12761521};
    12771522\end{cfa}
    1278 
    1279 
    1280 \subsection{Mutex Acquisition}
    1281 \label{s:MutexAcquisition}
    1282 
    1283 While correctness implicitly implies a monitor's mutual exclusion is acquired and released, there are implementation options about when and where the locking/unlocking occurs.
    1284 (Much of this discussion also applies to basic locks.)
    1285 For example, a monitor may need to be passed through multiple helper routines before it becomes necessary to acquire the monitor mutual-exclusion.
    1286 \begin{cfa}[morekeywords=nomutex]
    1287 monitor Aint { int cnt; };                                      $\C{// atomic integer counter}$
    1288 void ?{}( Aint & `nomutex` this ) with( this ) { cnt = 0; } $\C{// constructor}$
    1289 int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions}$
    1290 void ?{}( int & this, Aint & `mutex`$\(_{opt}\)$ v ) { this = v.cnt; }
    1291 int ?=?( int & lhs, Aint & `mutex`$\(_{opt}\)$ rhs ) with( rhs ) { lhs = cnt; }
    1292 int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
    1293 \end{cfa}
    1294 The @Aint@ constructor, @?{}@, uses the \lstinline[morekeywords=nomutex]@nomutex@ qualifier indicating mutual exclusion is unnecessary during construction because an object is inaccessible (private) until after it is initialized.
    1295 (While a constructor may publish its address into a global variable, doing so generates a race-condition.)
    1296 The conversion operators for initializing and assigning with a normal integer only need @mutex@, if reading/writing the implementation type is not atomic.
    1297 Finally, the prefix increment operato, @++?@, is normally @mutex@ to protect the incrementing from race conditions, unless there is an atomic increment instruction for the implementation type.
    1298 
    1299 The atomic counter is used without any explicit mutual-exclusion and provides thread-safe semantics, which is similar to the \CC template @std::atomic@.
    1300 \begin{cfa}
    1301 Aint x, y, z;
    1302 ++x; ++y; ++z;                                                          $\C{// safe increment by multiple threads}$
    1303 x = 2; y = 2; z = 2;                                            $\C{// conversions}$
    1304 int i = x, j = y, k = z;
    1305 i = x; j = y; k = z;
    1306 \end{cfa}
    1307 
    1308 For maximum usability, monitors have \newterm{multi-acquire} semantics allowing a thread to acquire it multiple times without deadlock.
    1309 For example, atomically printing the contents of a binary tree:
    1310 \begin{cfa}
    1311 monitor Tree {
    1312         Tree * left, right;
    1313         // value
    1314 };
    1315 void print( Tree & mutex tree ) {                       $\C{// prefix traversal}$
    1316         // write value
    1317         print( tree->left );                                    $\C{// multiply acquire monitor lock on each recursion}$
    1318         print( tree->right );
    1319 }
    1320 \end{cfa}
    1321 
    1322 Mandatory monitor qualifiers have the benefit of being self-documented, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameter is redundant.
    1323 Instead, one of qualifier semantics can be the default, and the other required.
    1324 For example, assume the safe @mutex@ option for a monitor parameter because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
    1325 On the other hand, assuming \lstinline[morekeywords=nomutex]@nomutex@ is the \emph{normal} parameter behaviour, stating explicitly ``this parameter is not special''.
    1326 Providing a default qualifier implies knowing whether a parameter is a monitor.
    1327 Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred.
    1328 For this reason, \CFA requires programmers to identify the kind of parameter with the @mutex@ keyword and uses no keyword to mean \lstinline[morekeywords=nomutex]@nomutex@.
    1329 
    1330 The next semantic decision is establishing which parameter \emph{types} may be qualified with @mutex@.
    1331 Given:
    1332 \begin{cfa}
    1333 monitor M { ... }
    1334 int f1( M & mutex m );
    1335 int f2( M * mutex m );
    1336 int f3( M * mutex m[] );
    1337 int f4( stack( M * ) & mutex m );
    1338 \end{cfa}
    1339 the issue is that some of these parameter types are composed of multiple objects.
    1340 For @f1@, there is only a single parameter object.
    1341 Adding indirection in @f2@ still identifies a single object.
    1342 However, the matrix in @f3@ introduces multiple objects.
    1343 While shown shortly, multiple acquisition is possible;
    1344 however array lengths are often unknown in C.
    1345 This issue is exacerbated in @f4@, where the data structure must be safely traversed to acquire all of its elements.
    1346 
    1347 To make the issue tractable, \CFA only acquires one monitor per parameter with at most one level of indirection.
    1348 However, the C type-system has an ambiguity with respects to arrays.
    1349 Is the argument for @f2@ a single object or an array of objects?
    1350 If it is an array, only the first element of the array is acquired, which seems unsafe;
    1351 hence, @mutex@ is disallowed for array parameters.
    1352 \begin{cfa}
    1353 int f1( M & mutex m );                                          $\C{// allowed: recommended case}$
    1354 int f2( M * mutex m );                                          $\C{// disallowed: could be an array}$
    1355 int f3( M mutex m[$\,$] );                                      $\C{// disallowed: array length unknown}$
    1356 int f4( M ** mutex m );                                         $\C{// disallowed: could be an array}$
    1357 int f5( M * mutex m[$\,$] );                            $\C{// disallowed: array length unknown}$
    1358 \end{cfa}
    1359 % Note, not all array routines have distinct types: @f2@ and @f3@ have the same type, as do @f4@ and @f5@.
    1360 % However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
    1361 
    1362 For object-oriented monitors, calling a mutex member \emph{implicitly} acquires mutual exclusion of the receiver object, @`rec`.foo(...)@.
    1363 \CFA has no receiver, and hence, must use an explicit mechanism to specify which object has mutual exclusion acquired.
    1364 A positive consequence of this design decision is the ability to support multi-monitor routines.
    1365 \begin{cfa}
    1366 int f( M & mutex x, M & mutex y );              $\C{// multiple monitor parameter of any type}$
    1367 M m1, m2;
    1368 f( m1, m2 );
    1369 \end{cfa}
    1370 (While object-oriented monitors can be extended with a mutex qualifier for multiple-monitor members, no prior example of this feature could be found.)
    1371 In practice, writing multi-locking routines that do not deadlock is tricky.
    1372 Having language support for such a feature is therefore a significant asset for \CFA.
    1373 
    1374 The capability to acquire multiple locks before entering a critical section is called \newterm{bulk acquire}.
    1375 In the previous example, \CFA guarantees the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
    1376 This consistent ordering means acquiring multiple monitors is safe from deadlock.
    1377 However, users can force the acquiring order.
    1378 For example, notice the use of @mutex@/\lstinline[morekeywords=nomutex]@nomutex@ and how this affects the acquiring order:
    1379 \begin{cfa}
    1380 void foo( M & mutex m1, M & mutex m2 );         $\C{// acquire m1 and m2}$
    1381 void bar( M & mutex m1, M & /* nomutex */ m2 ) { $\C{// acquire m1}$
    1382         ... foo( m1, m2 ); ...                                  $\C{// acquire m2}$
    1383 }
    1384 void baz( M & /* nomutex */ m1, M & mutex m2 ) { $\C{// acquire m2}$
    1385         ... foo( m1, m2 ); ...                                  $\C{// acquire m1}$
    1386 }
    1387 \end{cfa}
    1388 The multi-acquire semantics allows @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
    1389 In the calls to @bar@ and @baz@, the monitors are acquired in opposite order.
    1390 
    1391 However, such use leads to lock acquiring order problems resulting in deadlock~\cite{Lister77}, where detecting it requires dynamically tracking of monitor calls, and dealing with it requires rollback semantics~\cite{Dice10}.
    1392 In \CFA, safety is guaranteed by using bulk acquire of all monitors to shared objects, whereas other monitor systems provide no aid.
    1393 While \CFA provides only a partial solution, the \CFA partial solution handles many useful cases.
    1394 \begin{cfa}
    1395 monitor Bank { ... };
    1396 void deposit( Bank & `mutex` b, int deposit );
    1397 void transfer( Bank & `mutex` mybank, Bank & `mutex` yourbank, int me2you) {
    1398         deposit( mybank, `-`me2you );                   $\C{// debit}$
    1399         deposit( yourbank, me2you );                    $\C{// credit}$
    1400 }
    1401 \end{cfa}
    1402 This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
    1403 Without multi- and bulk acquire, the solution to this problem requires careful engineering.
    1404 
    1405 
    1406 \subsection{\protect\lstinline|mutex| statement} \label{mutex-stmt}
    1407 
    1408 The monitor call-semantics associate all locking semantics to routines.
    1409 Like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
    1410 \begin{cquote}
    1411 \begin{tabular}{@{}c|@{\hspace{\parindentlnth}}c@{}}
    1412 routine call & @mutex@ statement \\
    1413 \begin{cfa}
    1414 monitor M {};
    1415 void foo( M & mutex m1, M & mutex m2 ) {
    1416         // critical section
    1417 }
    1418 void bar( M & m1, M & m2 ) {
    1419         foo( m1, m2 );
    1420 }
    1421 \end{cfa}
    1422 &
    1423 \begin{cfa}
    1424 
    1425 void bar( M & m1, M & m2 ) {
    1426         mutex( m1, m2 ) {       // remove refactoring and naming
    1427                 // critical section
     1523Note that the destructor of a monitor must be a @mutex@ routine to prevent deallocation while a thread is accessing the monitor.
     1524As with any object, calls to a monitor, using @mutex@ or otherwise, is undefined behaviour after the destructor has run.
     1525
     1526% ======================================================================
     1527% ======================================================================
     1528\section{Internal Scheduling} \label{intsched}
     1529% ======================================================================
     1530% ======================================================================
     1531In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronization.
     1532With monitors, this capability is generally achieved with internal or external scheduling as in~\cite{Hoare74}.
     1533With \textbf{scheduling} loosely defined as deciding which thread acquires the critical section next, \textbf{internal scheduling} means making the decision from inside the critical section (\ie with access to the shared state), while \textbf{external scheduling} means making the decision when entering the critical section (\ie without access to the shared state).
     1534Since internal scheduling within a single monitor is mostly a solved problem, this paper concentrates on extending internal scheduling to multiple monitors.
     1535Indeed, like the \textbf{bulk-acq} semantics, internal scheduling extends to multiple monitors in a way that is natural to the user but requires additional complexity on the implementation side.
     1536
     1537First, here is a simple example of internal scheduling:
     1538
     1539\begin{cfa}
     1540monitor A {
     1541        condition e;
     1542}
     1543
     1544void foo(A& mutex a1, A& mutex a2) {
     1545        ...
     1546        // Wait for cooperation from bar()
     1547        wait(a1.e);
     1548        ...
     1549}
     1550
     1551void bar(A& mutex a1, A& mutex a2) {
     1552        // Provide cooperation for foo()
     1553        ...
     1554        // Unblock foo
     1555        signal(a1.e);
     1556}
     1557\end{cfa}
     1558There are two details to note here.
     1559First, @signal@ is a delayed operation; it only unblocks the waiting thread when it reaches the end of the critical section.
     1560This semantics is needed to respect mutual-exclusion, \ie the signaller and signalled thread cannot be in the monitor simultaneously.
     1561The alternative is to return immediately after the call to @signal@, which is significantly more restrictive.
     1562Second, in \CFA, while it is common to store a @condition@ as a field of the monitor, a @condition@ variable can be stored/created independently of a monitor.
     1563Here routine @foo@ waits for the @signal@ from @bar@ before making further progress, ensuring a basic ordering.
     1564
     1565An important aspect of the implementation is that \CFA does not allow barging, which means that once function @bar@ releases the monitor, @foo@ is guaranteed to be the next thread to acquire the monitor (unless some other thread waited on the same condition).
     1566This guarantee offers the benefit of not having to loop around waits to recheck that a condition is met.
     1567The main reason \CFA offers this guarantee is that users can easily introduce barging if it becomes a necessity but adding barging prevention or barging avoidance is more involved without language support.
     1568Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design and implementation of \CFA concurrency.
     1569
     1570% ======================================================================
     1571% ======================================================================
     1572\subsection{Internal Scheduling - Multi-Monitor}
     1573% ======================================================================
     1574% ======================================================================
     1575It is easy to understand the problem of multi-monitor scheduling using a series of pseudo-code examples.
     1576Note that for simplicity in the following snippets of pseudo-code, waiting and signalling is done using an implicit condition variable, like Java built-in monitors.
     1577Indeed, @wait@ statements always use the implicit condition variable as parameters and explicitly name the monitors (A and B) associated with the condition.
     1578Note that in \CFA, condition variables are tied to a \emph{group} of monitors on first use (called branding), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
     1579The example below shows the simple case of having two threads (one for each column) and a single monitor A.
     1580
     1581\begin{multicols}{2}
     1582thread 1
     1583\begin{cfa}
     1584acquire A
     1585        wait A
     1586release A
     1587\end{cfa}
     1588
     1589\columnbreak
     1590
     1591thread 2
     1592\begin{cfa}
     1593acquire A
     1594        signal A
     1595release A
     1596\end{cfa}
     1597\end{multicols}
     1598One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling.
     1599It is important to note here that both @wait@ and @signal@ must be called with the proper monitor(s) already acquired.
     1600This semantic is a logical requirement for barging prevention.
     1601
     1602A direct extension of the previous example is a \textbf{bulk-acq} version:
     1603\begin{multicols}{2}
     1604\begin{cfa}
     1605acquire A & B
     1606        wait A & B
     1607release A & B
     1608\end{cfa}
     1609\columnbreak
     1610\begin{cfa}
     1611acquire A & B
     1612        signal A & B
     1613release A & B
     1614\end{cfa}
     1615\end{multicols}
     1616\noindent This version uses \textbf{bulk-acq} (denoted using the {\sf\&} symbol), but the presence of multiple monitors does not add a particularly new meaning.
     1617Synchronization happens between the two threads in exactly the same way and order.
     1618The only difference is that mutual exclusion covers a group of monitors.
     1619On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
     1620
     1621While deadlock issues can occur when nesting monitors, these issues are only a symptom of the fact that locks, and by extension monitors, are not perfectly composable.
     1622For monitors, a well-known deadlock problem is the Nested Monitor Problem~\cite{Lister77}, which occurs when a @wait@ is made by a thread that holds more than one monitor.
     1623For example, the following cfa-code runs into the nested-monitor problem:
     1624\begin{multicols}{2}
     1625\begin{cfa}
     1626acquire A
     1627        acquire B
     1628                wait B
     1629        release B
     1630release A
     1631\end{cfa}
     1632
     1633\columnbreak
     1634
     1635\begin{cfa}
     1636acquire A
     1637        acquire B
     1638                signal B
     1639        release B
     1640release A
     1641\end{cfa}
     1642\end{multicols}
     1643\noindent The @wait@ only releases monitor @B@ so the signalling thread cannot acquire monitor @A@ to get to the @signal@.
     1644Attempting release of all acquired monitors at the @wait@ introduces a different set of problems, such as releasing monitor @C@, which has nothing to do with the @signal@.
     1645
     1646However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly.
     1647For example, the next cfa-code snippet acquires monitors {\sf A} then {\sf B} before waiting, while only acquiring {\sf B} when signalling, effectively avoiding the Nested Monitor Problem~\cite{Lister77}.
     1648
     1649\begin{multicols}{2}
     1650\begin{cfa}
     1651acquire A
     1652        acquire B
     1653                wait B
     1654        release B
     1655release A
     1656\end{cfa}
     1657
     1658\columnbreak
     1659
     1660\begin{cfa}
     1661
     1662acquire B
     1663        signal B
     1664release B
     1665
     1666\end{cfa}
     1667\end{multicols}
     1668
     1669\noindent However, this simple refactoring may not be possible, forcing more complex restructuring.
     1670
     1671% ======================================================================
     1672% ======================================================================
     1673\subsection{Internal Scheduling - In Depth}
     1674% ======================================================================
     1675% ======================================================================
     1676
     1677A larger example is presented to show complex issues for \textbf{bulk-acq} and its implementation options are analyzed.
     1678Figure~\ref{f:int-bulk-cfa} shows an example where \textbf{bulk-acq} adds a significant layer of complexity to the internal signalling semantics, and listing \ref{f:int-bulk-cfa} shows the corresponding \CFA code to implement the cfa-code in listing \ref{f:int-bulk-cfa}.
     1679For the purpose of translating the given cfa-code into \CFA-code, any method of introducing a monitor is acceptable, \eg @mutex@ parameters, global variables, pointer parameters, or using locals with the @mutex@ statement.
     1680
     1681\begin{figure}
     1682\begin{multicols}{2}
     1683Waiting thread
     1684\begin{cfa}[numbers=left]
     1685acquire A
     1686        // Code Section 1
     1687        acquire A & B
     1688                // Code Section 2
     1689                wait A & B
     1690                // Code Section 3
     1691        release A & B
     1692        // Code Section 4
     1693release A
     1694\end{cfa}
     1695\columnbreak
     1696Signalling thread
     1697\begin{cfa}[numbers=left, firstnumber=10,escapechar=|]
     1698acquire A
     1699        // Code Section 5
     1700        acquire A & B
     1701                // Code Section 6
     1702                |\label{line:signal1}|signal A & B
     1703                // Code Section 7
     1704        |\label{line:releaseFirst}|release A & B
     1705        // Code Section 8
     1706|\label{line:lastRelease}|release A
     1707\end{cfa}
     1708\end{multicols}
     1709\begin{cfa}[caption={Internal scheduling with \textbf{bulk-acq}},label={f:int-bulk-cfa}]
     1710\end{cfa}
     1711\begin{center}
     1712\begin{cfa}[xleftmargin=.4\textwidth]
     1713monitor A a;
     1714monitor B b;
     1715condition c;
     1716\end{cfa}
     1717\end{center}
     1718\begin{multicols}{2}
     1719Waiting thread
     1720\begin{cfa}
     1721mutex(a) {
     1722        // Code Section 1
     1723        mutex(a, b) {
     1724                // Code Section 2
     1725                wait(c);
     1726                // Code Section 3
    14281727        }
    1429 }
    1430 
    1431 \end{cfa}
    1432 \end{tabular}
    1433 \end{cquote}
    1434 
    1435 
    1436 \section{Scheduling}
    1437 \label{s:Scheduling}
    1438 
    1439 While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed.
    1440 For example, Figure~\ref{f:GenericBoundedBuffer} shows a bounded buffer that may be full/empty so produce/consumer threads must block.
    1441 Leaving the monitor and trying again (busy waiting) is impractical for high-level programming.
    1442 Monitors eliminate busy waiting by providing internal synchronization to schedule threads needing access to the shared data, where the synchronization is blocking (threads are parked) versus spinning.
    1443 Synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling, where \newterm{scheduling} defines which thread acquires the critical section next.
    1444 \newterm{Internal scheduling} is characterized by each thread entering the monitor and making an individual decision about proceeding or blocking, while \newterm{external scheduling} is characterized by an entering thread making a decision about proceeding for itself and on behalf of other threads attempting entry.
    1445 
    1446 Figure~\ref{f:BBInt} shows a \CFA bounded-buffer with internal scheduling, where producers/consumers enter the monitor, see the buffer is full/empty, and block on an appropriate condition lock, @full@/@empty@.
    1447 The @wait@ routine atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the routine's parameter list.
    1448 The appropriate condition lock is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
    1449 Signalling is unconditional, because signalling an empty condition lock does nothing.
    1450 
    1451 Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means:
    1452 \begin{enumerate}
    1453 \item
    1454 The signalling thread returns immediately, and the signalled thread continues.
    1455 \item
    1456 The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
    1457 \item
    1458 The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues.
    1459 \end{enumerate}
    1460 The first approach is too restrictive, as it precludes solving a reasonable class of problems, \eg dating service.
    1461 \CFA supports the next two semantics as both are useful.
    1462 Finally, while it is common to store a @condition@ as a field of the monitor, in \CFA, a @condition@ variable can be created/stored independently.
    1463 Furthermore, a condition variable is tied to a \emph{group} of monitors on first use (called \newterm{branding}), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
    1464 
    1465 \begin{figure}
    1466 \centering
    1467 \newbox\myboxA
    1468 \begin{lrbox}{\myboxA}
    1469 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1470 forall( otype T ) { // distribute forall
    1471         monitor Buffer {
    1472                 `condition` full, empty;
    1473                 int front, back, count;
    1474                 T elements[10];
    1475         };
    1476         void ?{}( Buffer(T) & buffer ) with(buffer) {
    1477                 [front, back, count] = 0;
     1728        // Code Section 4
     1729}
     1730\end{cfa}
     1731\columnbreak
     1732Signalling thread
     1733\begin{cfa}
     1734mutex(a) {
     1735        // Code Section 5
     1736        mutex(a, b) {
     1737                // Code Section 6
     1738                signal(c);
     1739                // Code Section 7
    14781740        }
    1479 
    1480         void insert( Buffer(T) & mutex buffer, T elem )
    1481                                 with(buffer) {
    1482                 if ( count == 10 ) `wait( empty )`;
    1483                 // insert elem into buffer
    1484                 `signal( full )`;
    1485         }
    1486         T remove( Buffer(T) & mutex buffer ) with(buffer) {
    1487                 if ( count == 0 ) `wait( full )`;
    1488                 // remove elem from buffer
    1489                 `signal( empty )`;
    1490                 return elem;
    1491         }
    1492 }
    1493 \end{cfa}
    1494 \end{lrbox}
    1495 
    1496 \newbox\myboxB
    1497 \begin{lrbox}{\myboxB}
    1498 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1499 forall( otype T ) { // distribute forall
    1500         monitor Buffer {
    1501 
    1502                 int front, back, count;
    1503                 T elements[10];
    1504         };
    1505         void ?{}( Buffer(T) & buffer ) with(buffer) {
    1506                 [front, back, count] = 0;
    1507         }
    1508         T remove( Buffer(T) & mutex buffer ); // forward
    1509         void insert( Buffer(T) & mutex buffer, T elem )
    1510                                 with(buffer) {
    1511                 if ( count == 10 ) `waitfor( remove, buffer )`;
    1512                 // insert elem into buffer
    1513 
    1514         }
    1515         T remove( Buffer(T) & mutex buffer ) with(buffer) {
    1516                 if ( count == 0 ) `waitfor( insert, buffer )`;
    1517                 // remove elem from buffer
    1518 
    1519                 return elem;
    1520         }
    1521 }
    1522 \end{cfa}
    1523 \end{lrbox}
    1524 
    1525 \subfloat[Internal Scheduling]{\label{f:BBInt}\usebox\myboxA}
    1526 %\qquad
    1527 \subfloat[External Scheduling]{\label{f:BBExt}\usebox\myboxB}
    1528 \caption{Generic Bounded-Buffer}
    1529 \label{f:GenericBoundedBuffer}
     1741        // Code Section 8
     1742}
     1743\end{cfa}
     1744\end{multicols}
     1745\begin{cfa}[caption={Equivalent \CFA code for listing \ref{f:int-bulk-cfa}},label={f:int-bulk-cfa}]
     1746\end{cfa}
     1747\begin{multicols}{2}
     1748Waiter
     1749\begin{cfa}[numbers=left]
     1750acquire A
     1751        acquire A & B
     1752                wait A & B
     1753        release A & B
     1754release A
     1755\end{cfa}
     1756
     1757\columnbreak
     1758
     1759Signaller
     1760\begin{cfa}[numbers=left, firstnumber=6,escapechar=|]
     1761acquire A
     1762        acquire A & B
     1763                signal A & B
     1764        release A & B
     1765        |\label{line:secret}|// Secretly keep B here
     1766release A
     1767// Wakeup waiter and transfer A & B
     1768\end{cfa}
     1769\end{multicols}
     1770\begin{cfa}[caption={Figure~\ref{f:int-bulk-cfa}, with delayed signalling comments},label={f:int-secret}]
     1771\end{cfa}
    15301772\end{figure}
    15311773
    1532 Figure~\ref{f:BBExt} shows a \CFA bounded-buffer with external scheduling, where producers/consumers detecting a full/empty buffer block and prevent more producers/consumers from entering the monitor until the buffer has a free/empty slot.
    1533 External scheduling is controlled by the @waitfor@ statement, which atomically blocks the calling thread, releases the monitor lock, and restricts the routine calls that can next acquire mutual exclusion.
    1534 If the buffer is full, only calls to @remove@ can acquire the buffer, and if the buffer is empty, only calls to @insert@ can acquire the buffer.
    1535 Threads making calls to routines that are currently excluded block outside (external) of the monitor on a calling queue, versus blocking on condition queues inside (internal) of the monitor.
    1536 % External scheduling is more constrained and explicit, which helps programmers reduce the non-deterministic nature of concurrency.
    1537 External scheduling allows users to wait for events from other threads without concern of unrelated events occurring.
    1538 The mechnaism can be done in terms of control flow, \eg Ada @accept@ or \uC @_Accept@, or in terms of data, \eg Go channels.
    1539 While both mechanisms have strengths and weaknesses, this project uses a control-flow mechanism to stay consistent with other language semantics.
    1540 Two challenges specific to \CFA for external scheduling are loose object-definitions (see Section~\ref{s:LooseObjectDefinitions}) and multiple-monitor routines (see Section~\ref{s:Multi-MonitorScheduling}).
    1541 
    1542 For internal scheduling, non-blocking signalling (as in the producer/consumer example) is used when the signaller is providing the cooperation for a waiting thread;
    1543 the signaller enters the monitor and changes state, detects a waiting threads that can use the state, performs a non-blocking signal on the condition queue for the waiting thread, and exits the monitor to run concurrently.
    1544 The waiter unblocks next, uses/takes the state, and exits the monitor.
    1545 Blocking signalling is the reverse, where the waiter is providing the cooperation for the signalling thread;
    1546 the signaller enters the monitor, detects a waiting thread providing the necessary state, performs a blocking signal to place it on the urgent queue and unblock the waiter.
    1547 The waiter changes state and exits the monitor, and the signaller unblocks next from the urgent queue to use/take the state.
    1548 
    1549 Figure~\ref{f:DatingService} shows a dating service demonstrating the two forms of signalling: non-blocking and blocking.
    1550 The dating service matches girl and boy threads with matching compatibility codes so they can exchange phone numbers.
    1551 A thread blocks until an appropriate partner arrives.
    1552 The complexity is exchanging phone number in the monitor because the monitor mutual-exclusion property prevents exchanging numbers.
    1553 For internal scheduling, the @exchange@ condition is necessary to block the thread finding the match, while the matcher unblocks to take the oppose number, post its phone number, and unblock the partner.
    1554 For external scheduling, the implicit urgent-condition replaces the explict @exchange@-condition and @signal_block@ puts the finding thread on the urgent condition and unblocks the matcher..
    1555 
    1556 The dating service is an example of a monitor that cannot be written using external scheduling because it requires knowledge of calling parameters to make scheduling decisions, and parameters of waiting threads are unavailable;
    1557 as well, an arriving thread may not find a partner and must wait, which requires a condition variable, and condition variables imply internal scheduling.
    1558 
    1559 \begin{figure}
    1560 \centering
    1561 \newbox\myboxA
    1562 \begin{lrbox}{\myboxA}
    1563 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1564 enum { CCodes = 20 };
    1565 monitor DS {
    1566         int GirlPhNo, BoyPhNo;
    1567         condition Girls[CCodes], Boys[CCodes];
    1568         condition exchange;
    1569 };
    1570 int girl( DS & mutex ds, int phNo, int ccode ) {
    1571         if ( is_empty( Boys[ccode] ) ) {
    1572                 wait( Girls[ccode] );
    1573                 GirlPhNo = phNo;
    1574                 exchange.signal();
    1575         } else {
    1576                 GirlPhNo = phNo;
    1577                 signal( Boys[ccode] );
    1578                 exchange.wait();
    1579         } // if
    1580         return BoyPhNo;
    1581 }
    1582 int boy( DS & mutex ds, int phNo, int ccode ) {
    1583         // as above with boy/girl interchanged
    1584 }
    1585 \end{cfa}
    1586 \end{lrbox}
    1587 
    1588 \newbox\myboxB
    1589 \begin{lrbox}{\myboxB}
    1590 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1591 
    1592 monitor DS {
    1593         int GirlPhNo, BoyPhNo;
    1594         condition Girls[CCodes], Boys[CCodes];
    1595 
    1596 };
    1597 int girl( DS & mutex ds, int phNo, int ccode ) {
    1598         if ( is_empty( Boys[ccode] ) ) { // no compatible
    1599                 wait( Girls[ccode] ); // wait for boy
    1600                 GirlPhNo = phNo; // make phone number available
    1601 
    1602         } else {
    1603                 GirlPhNo = phNo; // make phone number available
    1604                 signal_block( Boys[ccode] ); // restart boy
    1605 
    1606         } // if
    1607         return BoyPhNo;
    1608 }
    1609 int boy( DS & mutex ds, int phNo, int ccode ) {
    1610         // as above with boy/girl interchanged
    1611 }
    1612 \end{cfa}
    1613 \end{lrbox}
    1614 
    1615 \subfloat[\lstinline@signal@]{\label{f:DatingSignal}\usebox\myboxA}
    1616 \qquad
    1617 \subfloat[\lstinline@signal_block@]{\label{f:DatingSignalBlock}\usebox\myboxB}
    1618 \caption{Dating service. }
    1619 \label{f:DatingService}
    1620 \end{figure}
    1621 
    1622 Both internal and external scheduling extend to multiple monitors in a natural way.
    1623 \begin{cquote}
    1624 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
    1625 \begin{cfa}
    1626 monitor M { `condition e`; ... };
    1627 void foo( M & mutex m1, M & mutex m2 ) {
    1628         ... wait( `e` ); ...   // wait( e, m1, m2 )
    1629         ... wait( `e, m1` ); ...
    1630         ... wait( `e, m2` ); ...
    1631 }
    1632 \end{cfa}
    1633 &
    1634 \begin{cfa}
    1635 void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
    1636 void rtn$\(_2\)$( M & mutex m1 );
    1637 void bar( M & mutex m1, M & mutex m2 ) {
    1638         ... waitfor( `rtn` ); ...       // $\LstCommentStyle{waitfor( rtn\(_1\), m1, m2 )}$
    1639         ... waitfor( `rtn, m1` ); ... // $\LstCommentStyle{waitfor( rtn\(_2\), m1 )}$
    1640 }
    1641 \end{cfa}
    1642 \end{tabular}
    1643 \end{cquote}
    1644 For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex types in the parameter list, \ie @wait( e, m1, m2 )@.
    1645 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
    1646 Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.
    1647 Finally, a signaller,
    1648 \begin{cfa}
    1649 void baz( M & mutex m1, M & mutex m2 ) {
    1650         ... signal( e ); ...
    1651 }
    1652 \end{cfa}
    1653 must have acquired monitor locks that are greater than or equal to the number of locks for the waiting thread signalled from the condition queue.
    1654 
    1655 Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex types in the parameter list, \ie @waitfor( rtn, m1, m2 )@.
    1656 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
    1657 Waitfor statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer.
    1658 To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible.
    1659 
    1660 Given the ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
    1661 \begin{cfa}
    1662 void foo( M & mutex m1, M & mutex m2 ) {
    1663         ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
    1664 void bar( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
    1665         ... signal( `e` ); ...
    1666 \end{cfa}
    1667 The @wait@ only releases @m1@ so the signalling thread cannot acquire both @m1@ and @m2@ to  enter @bar@ to get to the @signal@.
    1668 While deadlock issues can occur with multiple/nesting acquisition, this issue results from the fact that locks, and by extension monitors, are not perfectly composable.
    1669 
    1670 Finally, an important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
    1671 If barging is allowed, synchronization between a singller and signallee is difficult, often requiring multiple unblock/block cycles (looping around a wait rechecking if a condition is met).
    1672 \begin{quote}
    1673 However, we decree that a signal operation be followed immediately by resumption of a waiting program, without possibility of an intervening procedure call from yet a third program.
    1674 It is only in this way that a waiting program has an absolute guarantee that it can acquire the resource just released by the signalling program without any danger that a third program will interpose a monitor entry and seize the resource instead.~\cite[p.~550]{Hoare74}
    1675 \end{quote}
    1676 \CFA scheduling \emph{precludes} barging, which simplifies synchronization among threads in the monitor and increases correctness.
    1677 For example, there are no loops in either bounded buffer solution in Figure~\ref{f:GenericBoundedBuffer}.
    1678 Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design and implementation of \CFA concurrency.
    1679 
    1680 
    1681 \subsection{Barging Prevention}
    1682 
    1683 Figure~\ref{f:BargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
    1684 The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
    1685 The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
    1686 When the signalling thread reaches the end of the inner @mutex@ statement, it should transfer ownership of @m1@ and @m2@ to the waiting threads to prevent barging into the outer @mutex@ statement by another thread.
    1687 However, both the signalling and waiting thread W1 still need monitor @m1@.
    1688 
    1689 \begin{figure}
    1690 \newbox\myboxA
    1691 \begin{lrbox}{\myboxA}
    1692 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1693 monitor M m1, m2;
    1694 condition c;
    1695 mutex( m1 ) { // $\LstCommentStyle{\color{red}outer}$
    1696         ...
    1697         mutex( m1, m2 ) { // $\LstCommentStyle{\color{red}inner}$
    1698                 ... `signal( c )`; ...
    1699                 // m1, m2 acquired
    1700         } // $\LstCommentStyle{\color{red}release m2}$
    1701         // m1 acquired
    1702 } // release m1
    1703 \end{cfa}
    1704 \end{lrbox}
    1705 
    1706 \newbox\myboxB
    1707 \begin{lrbox}{\myboxB}
    1708 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1709 
    1710 
    1711 mutex( m1 ) {
    1712         ...
    1713         mutex( m1, m2 ) {
    1714                 ... `wait( c )`; // block and release m1, m2
    1715                 // m1, m2 acquired
    1716         } // $\LstCommentStyle{\color{red}release m2}$
    1717         // m1 acquired
    1718 } // release m1
    1719 \end{cfa}
    1720 \end{lrbox}
    1721 
    1722 \newbox\myboxC
    1723 \begin{lrbox}{\myboxC}
    1724 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1725 
    1726 
    1727 mutex( m2 ) {
    1728         ... `wait( c )`; ...
    1729         // m2 acquired
    1730 } // $\LstCommentStyle{\color{red}release m2}$
    1731 
    1732 
    1733 
    1734 
    1735 \end{cfa}
    1736 \end{lrbox}
    1737 
    1738 \begin{cquote}
    1739 \subfloat[Signalling Thread]{\label{f:SignallingThread}\usebox\myboxA}
    1740 \hspace{2\parindentlnth}
    1741 \subfloat[Waiting Thread (W1)]{\label{f:WaitingThread}\usebox\myboxB}
    1742 \hspace{2\parindentlnth}
    1743 \subfloat[Waiting Thread (W2)]{\label{f:OtherWaitingThread}\usebox\myboxC}
    1744 \end{cquote}
    1745 \caption{Barging Prevention}
    1746 \label{f:BargingPrevention}
    1747 \end{figure}
    1748 
    1749 One scheduling solution is for the signaller to keep ownership of all locks until the last lock is ready to be transferred, because this semantics fits most closely to the behaviour of single-monitor scheduling.
    1750 However, Figure~\ref{f:OtherWaitingThread} shows this solution is complex depending on other waiters, resulting is choices when the signaller finishes the inner mutex-statement.
    1751 The singaller can retain @m2@ until completion of the outer mutex statement and pass the locks to waiter W1, or it can pass @m2@ to waiter W2 after completing the inner mutex-statement, while continuing to hold @m1@.
    1752 In the latter case, waiter W2 must eventually pass @m2@ to waiter W1, which is complex because W1 may have waited before W2, so W2 is unaware of it.
    1753 Furthermore, there is an execution sequence where the signaller always finds waiter W2, and hence, waiter W1 starves.
    1754 
    1755 While a number of approaches were examined~\cite[\S~4.3]{Delisle18}, the solution chosen for \CFA is a novel techique called \newterm{partial signalling}.
    1756 Signalled threads are moved to an urgent queue and the waiter at the front defines the set of monitors necessary for it to unblock.
    1757 Partial signalling transfers ownership of monitors to the front waiter.
    1758 When the signaller thread exits or waits in the monitor the front waiter is unblocked if all its monitors are released.
    1759 This solution has the benefit that complexity is encapsulated into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.
    1760 
    1761 \begin{comment}
     1774The complexity begins at code sections 4 and 8 in listing \ref{f:int-bulk-cfa}, which are where the existing semantics of internal scheduling needs to be extended for multiple monitors.
     1775The root of the problem is that \textbf{bulk-acq} is used in a context where one of the monitors is already acquired, which is why it is important to define the behaviour of the previous cfa-code.
     1776When the signaller thread reaches the location where it should ``release @A & B@'' (listing \ref{f:int-bulk-cfa} line \ref{line:releaseFirst}), it must actually transfer ownership of monitor @B@ to the waiting thread.
     1777This ownership transfer is required in order to prevent barging into @B@ by another thread, since both the signalling and signalled threads still need monitor @A@.
     1778There are three options:
     1779
     1780\subsubsection{Delaying Signals}
     1781The obvious solution to the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred.
     1782It can be argued that that moment is when the last lock is no longer needed, because this semantics fits most closely to the behaviour of single-monitor scheduling.
     1783This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from multiple objects to a single group of objects, effectively making the existing single-monitor semantic viable by simply changing monitors to monitor groups.
     1784This solution releases the monitors once every monitor in a group can be released.
     1785However, since some monitors are never released (\eg the monitor of a thread), this interpretation means a group might never be released.
     1786A more interesting interpretation is to transfer the group until all its monitors are released, which means the group is not passed further and a thread can retain its locks.
     1787
     1788However, listing \ref{f:int-secret} shows this solution can become much more complicated depending on what is executed while secretly holding B at line \ref{line:secret}, while avoiding the need to transfer ownership of a subset of the condition monitors.
    17621789Figure~\ref{f:dependency} shows a slightly different example where a third thread is waiting on monitor @A@, using a different condition variable.
    17631790Because the third thread is signalled when secretly holding @B@, the goal  becomes unreachable.
     
    17731800In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means knowing when to release a group becomes complex and inefficient (see next section) and therefore effectively precludes this approach.
    17741801
    1775 
    17761802\subsubsection{Dependency graphs}
     1803
    17771804
    17781805\begin{figure}
     
    18511878The extra challenge is that this dependency graph is effectively post-mortem, but the runtime system needs to be able to build and solve these graphs as the dependencies unfold.
    18521879Resolving dependency graphs being a complex and expensive endeavour, this solution is not the preferred one.
    1853 \end{comment}
    1854 
    1855 
    1856 \begin{comment}
     1880
     1881\subsubsection{Partial Signalling} \label{partial-sig}
     1882Finally, the solution that is chosen for \CFA is to use partial signalling.
     1883Again using listing \ref{f:int-bulk-cfa}, the partial signalling solution transfers ownership of monitor @B@ at lines \ref{line:signal1} to the waiter but does not wake the waiting thread since it is still using monitor @A@.
     1884Only when it reaches line \ref{line:lastRelease} does it actually wake up the waiting thread.
     1885This solution has the benefit that complexity is encapsulated into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.
     1886This solution has a much simpler implementation than a dependency graph solving algorithms, which is why it was chosen.
     1887Furthermore, after being fully implemented, this solution does not appear to have any significant downsides.
     1888
     1889Using partial signalling, listing \ref{f:dependency} can be solved easily:
     1890\begin{itemize}
     1891        \item When thread $\gamma$ reaches line \ref{line:release-ab} it transfers monitor @B@ to thread $\alpha$ and continues to hold monitor @A@.
     1892        \item When thread $\gamma$ reaches line \ref{line:release-a}  it transfers monitor @A@ to thread $\beta$  and wakes it up.
     1893        \item When thread $\beta$  reaches line \ref{line:release-aa} it transfers monitor @A@ to thread $\alpha$ and wakes it up.
     1894\end{itemize}
     1895
     1896% ======================================================================
     1897% ======================================================================
     1898\subsection{Signalling: Now or Later}
     1899% ======================================================================
     1900% ======================================================================
     1901\begin{table}
     1902\begin{tabular}{|c|c|}
     1903@signal@ & @signal_block@ \\
     1904\hline
     1905\begin{cfa}[tabsize=3]
     1906monitor DatingService {
     1907        // compatibility codes
     1908        enum{ CCodes = 20 };
     1909
     1910        int girlPhoneNo
     1911        int boyPhoneNo;
     1912};
     1913
     1914condition girls[CCodes];
     1915condition boys [CCodes];
     1916condition exchange;
     1917
     1918int girl(int phoneNo, int cfa) {
     1919        // no compatible boy ?
     1920        if(empty(boys[cfa])) {
     1921                wait(girls[cfa]);               // wait for boy
     1922                girlPhoneNo = phoneNo;          // make phone number available
     1923                signal(exchange);               // wake boy from chair
     1924        } else {
     1925                girlPhoneNo = phoneNo;          // make phone number available
     1926                signal(boys[cfa]);              // wake boy
     1927                wait(exchange);         // sit in chair
     1928        }
     1929        return boyPhoneNo;
     1930}
     1931int boy(int phoneNo, int cfa) {
     1932        // same as above
     1933        // with boy/girl interchanged
     1934}
     1935\end{cfa}&\begin{cfa}[tabsize=3]
     1936monitor DatingService {
     1937
     1938        enum{ CCodes = 20 };    // compatibility codes
     1939
     1940        int girlPhoneNo;
     1941        int boyPhoneNo;
     1942};
     1943
     1944condition girls[CCodes];
     1945condition boys [CCodes];
     1946// exchange is not needed
     1947
     1948int girl(int phoneNo, int cfa) {
     1949        // no compatible boy ?
     1950        if(empty(boys[cfa])) {
     1951                wait(girls[cfa]);               // wait for boy
     1952                girlPhoneNo = phoneNo;          // make phone number available
     1953                signal(exchange);               // wake boy from chair
     1954        } else {
     1955                girlPhoneNo = phoneNo;          // make phone number available
     1956                signal_block(boys[cfa]);                // wake boy
     1957
     1958                // second handshake unnecessary
     1959
     1960        }
     1961        return boyPhoneNo;
     1962}
     1963
     1964int boy(int phoneNo, int cfa) {
     1965        // same as above
     1966        // with boy/girl interchanged
     1967}
     1968\end{cfa}
     1969\end{tabular}
     1970\caption{Dating service example using \protect\lstinline|signal| and \protect\lstinline|signal_block|. }
     1971\label{tbl:datingservice}
     1972\end{table}
     1973An important note is that, until now, signalling a monitor was a delayed operation.
     1974The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the @signal@ statement.
     1975However, in some cases, it may be more convenient for users to immediately transfer ownership to the thread that is waiting for cooperation, which is achieved using the @signal_block@ routine.
     1976
     1977The example in table \ref{tbl:datingservice} highlights the difference in behaviour.
     1978As mentioned, @signal@ only transfers ownership once the current critical section exits; this behaviour requires additional synchronization when a two-way handshake is needed.
     1979To avoid this explicit synchronization, the @condition@ type offers the @signal_block@ routine, which handles the two-way handshake as shown in the example.
     1980This feature removes the need for a second condition variables and simplifies programming.
     1981Like every other monitor semantic, @signal_block@ uses barging prevention, which means mutual-exclusion is baton-passed both on the front end and the back end of the call to @signal_block@, meaning no other thread can acquire the monitor either before or after the call.
     1982
     1983% ======================================================================
     1984% ======================================================================
    18571985\section{External scheduling} \label{extsched}
    1858 
     1986% ======================================================================
     1987% ======================================================================
     1988An alternative to internal scheduling is external scheduling (see Table~\ref{tbl:sched}).
    18591989\begin{table}
    18601990\begin{tabular}{|c|c|c|}
     
    19202050\label{tbl:sched}
    19212051\end{table}
     2052This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
     2053Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
     2054External scheduling can generally be done either in terms of control flow (\eg Ada with @accept@, \uC with @_Accept@) or in terms of data (\eg Go with channels).
     2055Of course, both of these paradigms have their own strengths and weaknesses, but for this project, control-flow semantics was chosen to stay consistent with the rest of the languages semantics.
     2056Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multiple-monitor routines.
     2057The previous example shows a simple use @_Accept@ versus @wait@/@signal@ and its advantages.
     2058Note that while other languages often use @accept@/@select@ as the core external scheduling keyword, \CFA uses @waitfor@ to prevent name collisions with existing socket \textbf{api}s.
    19222059
    19232060For the @P@ member above using internal scheduling, the call to @wait@ only guarantees that @V@ is the last routine to access the monitor, allowing a third routine, say @isInUse()@, acquire mutual exclusion several times while routine @P@ is waiting.
    19242061On the other hand, external scheduling guarantees that while routine @P@ is waiting, no other routine than @V@ can acquire the monitor.
    1925 \end{comment}
    1926 
    1927 
     2062
     2063% ======================================================================
     2064% ======================================================================
    19282065\subsection{Loose Object Definitions}
    1929 \label{s:LooseObjectDefinitions}
    1930 
    1931 In an object-oriented programming-language, a class includes an exhaustive list of operations.
    1932 However, new members can be added via static inheritance or dynaic members, \eg JavaScript~\cite{JavaScript}.
    1933 Similarly, monitor routines can be added at any time in \CFA, making it less clear for programmers and more difficult to implement.
    1934 \begin{cfa}
    1935 monitor M {};
    1936 void `f`( M & mutex m );
    1937 void g( M & mutex m ) { waitfor( `f` ); }       $\C{// clear which f}$
    1938 void `f`( M & mutex m, int );                           $\C{// different f}$
    1939 void h( M & mutex m ) { waitfor( `f` ); }       $\C{// unclear which f}$
    1940 \end{cfa}
    1941 Hence, the cfa-code for the entering a monitor looks like:
    1942 \begin{cfa}
    1943 if ( $\textrm{\textit{monitor is free}}$ ) $\LstCommentStyle{// \color{red}enter}$
    1944 else if ( $\textrm{\textit{already own monitor}}$ ) $\LstCommentStyle{// \color{red}continue}$
    1945 else if ( $\textrm{\textit{monitor accepts me}}$ ) $\LstCommentStyle{// \color{red}enter}$
    1946 else $\LstCommentStyle{// \color{red}block}$
    1947 \end{cfa}
     2066% ======================================================================
     2067% ======================================================================
     2068In \uC, a monitor class declaration includes an exhaustive list of monitor operations.
     2069Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
     2070
     2071\begin{cfa}
     2072monitor A {};
     2073
     2074void f(A & mutex a);
     2075void g(A & mutex a) {
     2076        waitfor(f); // Obvious which f() to wait for
     2077}
     2078
     2079void f(A & mutex a, int); // New different F added in scope
     2080void h(A & mutex a) {
     2081        waitfor(f); // Less obvious which f() to wait for
     2082}
     2083\end{cfa}
     2084
     2085Furthermore, external scheduling is an example where implementation constraints become visible from the interface.
     2086Here is the cfa-code for the entering phase of a monitor:
     2087\begin{center}
     2088\begin{tabular}{l}
     2089\begin{cfa}
     2090        if monitor is free
     2091                enter
     2092        elif already own the monitor
     2093                continue
     2094        elif monitor accepts me
     2095                enter
     2096        else
     2097                block
     2098\end{cfa}
     2099\end{tabular}
     2100\end{center}
    19482101For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instructions.
    1949 However, a fast check for \emph{monitor accepts me} is much harder to implement depending on the constraints put on the monitors.
    1950 Figure~\ref{fig:ClassicalMonitor} shows monitors are often expressed as an entry (calling) queue, some acceptor queues, and an urgent stack/queue.
     2102However, a fast check for @monitor accepts me@ is much harder to implement depending on the constraints put on the monitors.
     2103Indeed, monitors are often expressed as an entry queue and some acceptor queue as in Figure~\ref{fig:ClassicalMonitor}.
    19512104
    19522105\begin{figure}
    19532106\centering
    1954 \subfloat[Classical monitor] {
     2107\subfloat[Classical Monitor] {
    19552108\label{fig:ClassicalMonitor}
    1956 {\resizebox{0.45\textwidth}{!}{\input{monitor.pstex_t}}}
     2109{\resizebox{0.45\textwidth}{!}{\input{monitor}}}
    19572110}% subfloat
    1958 \quad
    1959 \subfloat[Bulk acquire monitor] {
     2111\qquad
     2112\subfloat[\textbf{bulk-acq} Monitor] {
    19602113\label{fig:BulkMonitor}
    1961 {\resizebox{0.45\textwidth}{!}{\input{ext_monitor.pstex_t}}}
     2114{\resizebox{0.45\textwidth}{!}{\input{ext_monitor}}}
    19622115}% subfloat
    1963 \caption{Monitor Implementation}
    1964 \label{f:MonitorImplementation}
     2116\caption{External Scheduling Monitor}
    19652117\end{figure}
    19662118
    1967 For a fixed (small) number of mutex routines (\eg 128), the accept check reduces to a bitmask of allowed callers, which can be checked with a single instruction.
    1968 This approach requires a unique dense ordering of routines with a small upper-bound and the ordering must be consistent across translation units.
    1969 For object-oriented languages these constraints are common, but \CFA mutex routines can be added in any scope and are only visible in certain translation unit, precluding program-wide dense-ordering among mutex routines.
    1970 
    1971 Figure~\ref{fig:BulkMonitor} shows the \CFA monitor implementation.
    1972 The mutex routine called is associated with each thread on the entry queue, while a list of acceptable routines is kept separately.
    1973 The accepted list is a variable-sized array of accepted routine pointers, so the single instruction bitmask comparison is replaced by dereferencing a pointer followed by a linear search.
    1974 
    1975 \begin{comment}
     2119There are other alternatives to these pictures, but in the case of the left picture, implementing a fast accept check is relatively easy.
     2120Restricted to a fixed number of mutex members, N, the accept check reduces to updating a bitmask when the acceptor queue changes, a check that executes in a single instruction even with a fairly large number (\eg 128) of mutex members.
     2121This approach requires a unique dense ordering of routines with an upper-bound and that ordering must be consistent across translation units.
     2122For OO languages these constraints are common, since objects only offer adding member routines consistently across translation units via inheritance.
     2123However, in \CFA users can extend objects with mutex routines that are only visible in certain translation unit.
     2124This means that establishing a program-wide dense-ordering among mutex routines can only be done in the program linking phase, and still could have issues when using dynamically shared objects.
     2125
     2126The alternative is to alter the implementation as in Figure~\ref{fig:BulkMonitor}.
     2127Here, the mutex routine called is associated with a thread on the entry queue while a list of acceptable routines is kept separate.
     2128Generating a mask dynamically means that the storage for the mask information can vary between calls to @waitfor@, allowing for more flexibility and extensions.
     2129Storing an array of accepted function pointers replaces the single instruction bitmask comparison with dereferencing a pointer followed by a linear search.
     2130Furthermore, supporting nested external scheduling (\eg listing \ref{f:nest-ext}) may now require additional searches for the @waitfor@ statement to check if a routine is already queued.
     2131
    19762132\begin{figure}
    19772133\begin{cfa}[caption={Example of nested external scheduling},label={f:nest-ext}]
     
    19892145\end{figure}
    19902146
    1991 Note that in the right picture, tasks need to always keep track of the monitors associated with mutex routines, and the routine mask needs to have both a routine pointer and a set of monitors, as is discussed in the next section.
     2147Note that in the right picture, tasks need to always keep track of the monitors associated with mutex routines, and the routine mask needs to have both a function pointer and a set of monitors, as is discussed in the next section.
    19922148These details are omitted from the picture for the sake of simplicity.
    19932149
     
    19972153In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be  hard to write.
    19982154This decision is based on the assumption that writing fast but inflexible locks is closer to a solved problem than writing locks that are as flexible as external scheduling in \CFA.
    1999 \end{comment}
    2000 
    2001 
     2155
     2156% ======================================================================
     2157% ======================================================================
    20022158\subsection{Multi-Monitor Scheduling}
    2003 \label{s:Multi-MonitorScheduling}
     2159% ======================================================================
     2160% ======================================================================
    20042161
    20052162External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax.
    2006 Even in the simplest possible case, new semantics needs to be established:
     2163Even in the simplest possible case, some new semantics needs to be established:
    20072164\begin{cfa}
    20082165monitor M {};
    2009 void f( M & mutex m1 );
    2010 void g( M & mutex m1, M & mutex m2 ) {
    2011         waitfor( f );                                                   $\C{// pass m1 or m2 to f?}$
    2012 }
    2013 \end{cfa}
    2014 The solution is for the programmer to disambiguate:
    2015 \begin{cfa}
    2016         waitfor( f, m2 );                                               $\C{// wait for call to f with argument m2}$
    2017 \end{cfa}
    2018 Routine @g@ has acquired both locks, so when routine @f@ is called, the lock for monitor @m2@ is passed from @g@ to @f@ (while @g@ still holds lock @m1@).
    2019 This behaviour can be extended to the multi-monitor @waitfor@ statement.
     2166
     2167void f(M & mutex a);
     2168
     2169void g(M & mutex b, M & mutex c) {
     2170        waitfor(f); // two monitors M => unknown which to pass to f(M & mutex)
     2171}
     2172\end{cfa}
     2173The obvious solution is to specify the correct monitor as follows:
     2174
    20202175\begin{cfa}
    20212176monitor M {};
    2022 void f( M & mutex m1, M & mutex m2 );
    2023 void g( M & mutex m1, M & mutex m2 ) {
    2024         waitfor( f, m1, m2 );                                   $\C{// wait for call to f with arguments m1 and m2}$
    2025 }
    2026 \end{cfa}
    2027 Again, the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired by accepting routine.
     2177
     2178void f(M & mutex a);
     2179
     2180void g(M & mutex a, M & mutex b) {
     2181        // wait for call to f with argument b
     2182        waitfor(f, b);
     2183}
     2184\end{cfa}
     2185This syntax is unambiguous.
     2186Both locks are acquired and kept by @g@.
     2187When routine @f@ is called, the lock for monitor @b@ is temporarily transferred from @g@ to @f@ (while @g@ still holds lock @a@).
     2188This behaviour can be extended to the multi-monitor @waitfor@ statement as follows.
     2189
     2190\begin{cfa}
     2191monitor M {};
     2192
     2193void f(M & mutex a, M & mutex b);
     2194
     2195void g(M & mutex a, M & mutex b) {
     2196        // wait for call to f with arguments a and b
     2197        waitfor(f, a, b);
     2198}
     2199\end{cfa}
     2200
     2201Note that the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired in the routine. @waitfor@ used in any other context is undefined behaviour.
    20282202
    20292203An important behaviour to note is when a set of monitors only match partially:
     2204
    20302205\begin{cfa}
    20312206mutex struct A {};
     2207
    20322208mutex struct B {};
    2033 void g( A & mutex m1, B & mutex m2 ) {
    2034         waitfor( f, m1, m2 );
    2035 }
     2209
     2210void g(A & mutex a, B & mutex b) {
     2211        waitfor(f, a, b);
     2212}
     2213
    20362214A a1, a2;
    20372215B b;
     2216
    20382217void foo() {
    2039         g( a1, b ); // block on accept
    2040 }
     2218        g(a1, b); // block on accept
     2219}
     2220
    20412221void bar() {
    2042         f( a2, b ); // fulfill cooperation
     2222        f(a2, b); // fulfill cooperation
    20432223}
    20442224\end{cfa}
     
    20472227It is also important to note that in the case of external scheduling the order of parameters is irrelevant; @waitfor(f,a,b)@ and @waitfor(f,b,a)@ are indistinguishable waiting condition.
    20482228
    2049 
     2229% ======================================================================
     2230% ======================================================================
    20502231\subsection{\protect\lstinline|waitfor| Semantics}
    2051 
    2052 Syntactically, the @waitfor@ statement takes a routine identifier and a set of monitors.
    2053 While the set of monitors can be any list of expressions, the routine name is more restricted because the compiler validates at compile time the validity of the routine type and the parameters used with the @waitfor@ statement.
    2054 It checks that the set of monitors passed in matches the requirements for a routine call.
     2232% ======================================================================
     2233% ======================================================================
     2234
     2235Syntactically, the @waitfor@ statement takes a function identifier and a set of monitors.
     2236While the set of monitors can be any list of expressions, the function name is more restricted because the compiler validates at compile time the validity of the function type and the parameters used with the @waitfor@ statement.
     2237It checks that the set of monitors passed in matches the requirements for a function call.
    20552238Figure~\ref{f:waitfor} shows various usages of the waitfor statement and which are acceptable.
    2056 The choice of the routine type is made ignoring any non-@mutex@ parameter.
     2239The choice of the function type is made ignoring any non-@mutex@ parameter.
    20572240One limitation of the current implementation is that it does not handle overloading, but overloading is possible.
    20582241\begin{figure}
     
    20802263        waitfor(f2, a1, a2); // Incorrect : Mutex arguments don't match
    20812264        waitfor(f1, 1);      // Incorrect : 1 not a mutex argument
    2082         waitfor(f9, a1);     // Incorrect : f9 routine does not exist
     2265        waitfor(f9, a1);     // Incorrect : f9 function does not exist
    20832266        waitfor(*fp, a1 );   // Incorrect : fp not an identifier
    20842267        waitfor(f4, a1);     // Incorrect : f4 ambiguous
     
    20902273
    20912274Finally, for added flexibility, \CFA supports constructing a complex @waitfor@ statement using the @or@, @timeout@ and @else@.
    2092 Indeed, multiple @waitfor@ clauses can be chained together using @or@; this chain forms a single statement that uses baton pass to any routine that fits one of the routine+monitor set passed in.
    2093 To enable users to tell which accepted routine executed, @waitfor@s are followed by a statement (including the null statement @;@) or a compound statement, which is executed after the clause is triggered.
    2094 A @waitfor@ chain can also be followed by a @timeout@, to signify an upper bound on the wait, or an @else@, to signify that the call should be non-blocking, which checks for a matching routine call already arrived and otherwise continues.
     2275Indeed, multiple @waitfor@ clauses can be chained together using @or@; this chain forms a single statement that uses baton pass to any function that fits one of the function+monitor set passed in.
     2276To enable users to tell which accepted function executed, @waitfor@s are followed by a statement (including the null statement @;@) or a compound statement, which is executed after the clause is triggered.
     2277A @waitfor@ chain can also be followed by a @timeout@, to signify an upper bound on the wait, or an @else@, to signify that the call should be non-blocking, which checks for a matching function call already arrived and otherwise continues.
    20952278Any and all of these clauses can be preceded by a @when@ condition to dynamically toggle the accept clauses on or off based on some current state.
    20962279Figure~\ref{f:waitfor2} demonstrates several complex masks and some incorrect ones.
     
    21472330\end{figure}
    21482331
    2149 
     2332% ======================================================================
     2333% ======================================================================
    21502334\subsection{Waiting For The Destructor}
    2151 
     2335% ======================================================================
     2336% ======================================================================
    21522337An interesting use for the @waitfor@ statement is destructor semantics.
    21532338Indeed, the @waitfor@ statement can accept any @mutex@ routine, which includes the destructor (see section \ref{data}).
     
    21762361
    21772362
     2363% ######     #    ######     #    #       #       ####### #       ###  #####  #     #
     2364% #     #   # #   #     #   # #   #       #       #       #        #  #     # ##   ##
     2365% #     #  #   #  #     #  #   #  #       #       #       #        #  #       # # # #
     2366% ######  #     # ######  #     # #       #       #####   #        #   #####  #  #  #
     2367% #       ####### #   #   ####### #       #       #       #        #        # #     #
     2368% #       #     # #    #  #     # #       #       #       #        #  #     # #     #
     2369% #       #     # #     # #     # ####### ####### ####### ####### ###  #####  #     #
    21782370\section{Parallelism}
    2179 
    21802371Historically, computer performance was about processor speeds and instruction counts.
    21812372However, with heat dissipation being a direct consequence of speed increase, parallelism has become the new source for increased performance~\cite{Sutter05, Sutter05b}.
     
    21872378While there are many variations of the presented paradigms, most of these variations do not actually change the guarantees or the semantics, they simply move costs in order to achieve better performance for certain workloads.
    21882379
    2189 
    21902380\section{Paradigms}
    2191 
    2192 
    21932381\subsection{User-Level Threads}
    2194 
    21952382A direct improvement on the \textbf{kthread} approach is to use \textbf{uthread}.
    21962383These threads offer most of the same features that the operating system already provides but can be used on a much larger scale.
     
    22012388Examples of languages that support \textbf{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    22022389
    2203 
    22042390\subsection{Fibers : User-Level Threads Without Preemption} \label{fibers}
    2205 
    22062391A popular variant of \textbf{uthread} is what is often referred to as \textbf{fiber}.
    22072392However, \textbf{fiber} do not present meaningful semantic differences with \textbf{uthread}.
     
    22122397An example of a language that uses fibers is Go~\cite{Go}
    22132398
    2214 
    22152399\subsection{Jobs and Thread Pools}
    2216 
    22172400An approach on the opposite end of the spectrum is to base parallelism on \textbf{pool}.
    22182401Indeed, \textbf{pool} offer limited flexibility but at the benefit of a simpler user interface.
     
    22252408The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    22262409
    2227 
    22282410\subsection{Paradigm Performance}
    2229 
    22302411While the choice between the three paradigms listed above may have significant performance implications, it is difficult to pin down the performance implications of choosing a model at the language level.
    22312412Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload.
     
    22352416Finally, if the units of uninterrupted work are large, enough the paradigm choice is largely amortized by the actual work done.
    22362417
    2237 
    22382418\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
    2239 
    22402419A \textbf{cfacluster} is a group of \textbf{kthread} executed in isolation. \textbf{uthread} are scheduled on the \textbf{kthread} of a given \textbf{cfacluster}, allowing organization between \textbf{uthread} and \textbf{kthread}.
    22412420It is important that \textbf{kthread} belonging to a same \textbf{cfacluster} have homogeneous settings, otherwise migrating a \textbf{uthread} from one \textbf{kthread} to the other can cause issues.
     
    22452424Currently \CFA only supports one \textbf{cfacluster}, the initial one.
    22462425
    2247 
    22482426\subsection{Future Work: Machine Setup}\label{machine}
    2249 
    22502427While this was not done in the context of this paper, another important aspect of clusters is affinity.
    22512428While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heterogeneous setups.
     
    22532430OS support for CPU affinity is now common~\cite{affinityLinux, affinityWindows, affinityFreebsd, affinityNetbsd, affinityMacosx}, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
    22542431
    2255 
    22562432\subsection{Paradigms}\label{cfaparadigms}
    2257 
    22582433Given these building blocks, it is possible to reproduce all three of the popular paradigms.
    22592434Indeed, \textbf{uthread} is the default paradigm in \CFA.
     
    22632438
    22642439
     2440
    22652441\section{Behind the Scenes}
    2266 
    22672442There are several challenges specific to \CFA when implementing concurrency.
    2268 These challenges are a direct result of bulk acquire and loose object definitions.
     2443These challenges are a direct result of \textbf{bulk-acq} and loose object definitions.
    22692444These two constraints are the root cause of most design decisions in the implementation.
    22702445Furthermore, to avoid contention from dynamically allocating memory in a concurrent environment, the internal-scheduling design is (almost) entirely free of mallocs.
     
    22742449The main memory concern for concurrency is queues.
    22752450All blocking operations are made by parking threads onto queues and all queues are designed with intrusive nodes, where each node has pre-allocated link fields for chaining, to avoid the need for memory allocation.
    2276 Since several concurrency operations can use an unbound amount of memory (depending on bulk acquire), statically defining information in the intrusive fields of threads is insufficient.The only way to use a variable amount of memory without requiring memory allocation is to pre-allocate large buffers of memory eagerly and store the information in these buffers.
     2451Since several concurrency operations can use an unbound amount of memory (depending on \textbf{bulk-acq}), statically defining information in the intrusive fields of threads is insufficient.The only way to use a variable amount of memory without requiring memory allocation is to pre-allocate large buffers of memory eagerly and store the information in these buffers.
    22772452Conveniently, the call stack fits that description and is easy to use, which is why it is used heavily in the implementation of internal scheduling, particularly variable-length arrays.
    22782453Since stack allocation is based on scopes, the first step of the implementation is to identify the scopes that are available to store the information, and which of these can have a variable-length array.
    22792454The threads and the condition both have a fixed amount of memory, while @mutex@ routines and blocking calls allow for an unbound amount, within the stack size.
    22802455
    2281 Note that since the major contributions of this paper are extending monitor semantics to bulk acquire and loose object definitions, any challenges that are not resulting of these characteristics of \CFA are considered as solved problems and therefore not discussed.
    2282 
    2283 
     2456Note that since the major contributions of this paper are extending monitor semantics to \textbf{bulk-acq} and loose object definitions, any challenges that are not resulting of these characteristics of \CFA are considered as solved problems and therefore not discussed.
     2457
     2458% ======================================================================
     2459% ======================================================================
    22842460\section{Mutex Routines}
     2461% ======================================================================
     2462% ======================================================================
    22852463
    22862464The first step towards the monitor implementation is simple @mutex@ routines.
     
    23172495\end{figure}
    23182496
    2319 
    23202497\subsection{Details: Interaction with polymorphism}
    2321 
    23222498Depending on the choice of semantics for when monitor locks are acquired, interaction between monitors and \CFA's concept of polymorphism can be more complex to support.
    23232499However, it is shown that entry-point locking solves most of the issues.
     
    23882564void foo(T * mutex t);
    23892565
    2390 // Correct: this routine only works on monitors (any monitor)
     2566// Correct: this function only works on monitors (any monitor)
    23912567forall(dtype T | is_monitor(T))
    23922568void bar(T * mutex t));
     
    23952571Both entry point and \textbf{callsite-locking} are feasible implementations.
    23962572The current \CFA implementation uses entry-point locking because it requires less work when using \textbf{raii}, effectively transferring the burden of implementation to object construction/destruction.
    2397 It is harder to use \textbf{raii} for call-site locking, as it does not necessarily have an existing scope that matches exactly the scope of the mutual exclusion, \ie the routine body.
     2573It is harder to use \textbf{raii} for call-site locking, as it does not necessarily have an existing scope that matches exactly the scope of the mutual exclusion, \ie the function body.
    23982574For example, the monitor call can appear in the middle of an expression.
    23992575Furthermore, entry-point locking requires less code generation since any useful routine is called multiple times but there is only one entry point for many call sites.
    24002576
    2401 
     2577% ======================================================================
     2578% ======================================================================
    24022579\section{Threading} \label{impl:thread}
     2580% ======================================================================
     2581% ======================================================================
    24032582
    24042583Figure \ref{fig:system1} shows a high-level picture if the \CFA runtime system in regards to concurrency.
     
    24132592\end{figure}
    24142593
    2415 
    24162594\subsection{Processors}
    2417 
    24182595Parallelism in \CFA is built around using processors to specify how much parallelism is desired. \CFA processors are object wrappers around kernel threads, specifically @pthread@s in the current implementation of \CFA.
    24192596Indeed, any parallelism must go through operating-system libraries.
     
    24232600Processors internally use coroutines to take advantage of the existing context-switching semantics.
    24242601
    2425 
    24262602\subsection{Stack Management}
    2427 
    24282603One of the challenges of this system is to reduce the footprint as much as possible.
    24292604Specifically, all @pthread@s created also have a stack created with them, which should be used as much as possible.
     
    24322607In order to respect C user expectations, the stack of the initial kernel thread, the main stack of the program, is used by the main user thread rather than the main processor, which can grow very large.
    24332608
    2434 
    24352609\subsection{Context Switching}
    2436 
    24372610As mentioned in section \ref{coroutine}, coroutines are a stepping stone for implementing threading, because they share the same mechanism for context-switching between different stacks.
    2438 To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific routine call.
     2611To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific function call.
    24392612This assumption means that the context-switch only has to copy the callee-saved registers onto the stack and then switch the stack registers with the ones of the target coroutine/thread.
    2440 Note that the instruction pointer can be left untouched since the context-switch is always inside the same routine
     2613Note that the instruction pointer can be left untouched since the context-switch is always inside the same function.
    24412614Threads, however, do not context-switch between each other directly.
    24422615They context-switch to the scheduler.
     
    24482621This option is not currently present in \CFA, but the changes required to add it are strictly additive.
    24492622
    2450 
    24512623\subsection{Preemption} \label{preemption}
    2452 
    24532624Finally, an important aspect for any complete threading system is preemption.
    24542625As mentioned in section \ref{basics}, preemption introduces an extra degree of uncertainty, which enables users to have multiple threads interleave transparently, rather than having to cooperate among threads for proper scheduling and CPU distribution.
     
    24772648As a result, a signal handler can start on one kernel thread and terminate on a second kernel thread (but the same user thread).
    24782649It is important to note that signal handlers save and restore signal masks because user-thread migration can cause a signal mask to migrate from one kernel thread to another.
    2479 This behaviour is only a problem if all kernel threads, among which a user thread can migrate, differ in terms of signal masks\footnote{Sadly, official POSIX documentation is silent on what distinguishes ``async-signal-safe'' routines from other routines}.
     2650This behaviour is only a problem if all kernel threads, among which a user thread can migrate, differ in terms of signal masks\footnote{Sadly, official POSIX documentation is silent on what distinguishes ``async-signal-safe'' functions from other functions.}.
    24802651However, since the kernel thread handling preemption requires a different signal mask, executing user threads on the kernel-alarm thread can cause deadlocks.
    24812652For this reason, the alarm thread is in a tight loop around a system call to @sigwaitinfo@, requiring very little CPU time for preemption.
     
    24842655Indeed, @sigwait@ can differentiate signals sent from @pthread_sigqueue@ from signals sent from alarms or the kernel.
    24852656
    2486 
    24872657\subsection{Scheduler}
    24882658Finally, an aspect that was not mentioned yet is the scheduling algorithm.
     
    24902660Further discussion on scheduling is present in section \ref{futur:sched}.
    24912661
    2492 
     2662% ======================================================================
     2663% ======================================================================
    24932664\section{Internal Scheduling} \label{impl:intsched}
    2494 
     2665% ======================================================================
     2666% ======================================================================
    24952667The following figure is the traditional illustration of a monitor (repeated from page~\pageref{fig:ClassicalMonitor} for convenience):
    24962668
    24972669\begin{figure}
    24982670\begin{center}
    2499 {\resizebox{0.4\textwidth}{!}{\input{monitor.pstex_t}}}
     2671{\resizebox{0.4\textwidth}{!}{\input{monitor}}}
    25002672\end{center}
    25012673\caption{Traditional illustration of a monitor}
     
    25062678
    25072679For \CFA, this picture does not have support for blocking multiple monitors on a single condition.
    2508 To support bulk acquire two changes to this picture are required.
     2680To support \textbf{bulk-acq} two changes to this picture are required.
    25092681First, it is no longer helpful to attach the condition to \emph{a single} monitor.
    25102682Secondly, the thread waiting on the condition has to be separated across multiple monitors, seen in figure \ref{fig:monitor_cfa}.
     
    25552727\end{figure}
    25562728
    2557 The solution discussed in \ref{s:InternalScheduling} can be seen in the exit routine of listing \ref{f:entry2}.
     2729The solution discussed in \ref{intsched} can be seen in the exit routine of listing \ref{f:entry2}.
    25582730Basically, the solution boils down to having a separate data structure for the condition queue and the AS-stack, and unconditionally transferring ownership of the monitors but only unblocking the thread when the last monitor has transferred ownership.
    25592731This solution is deadlock safe as well as preventing any potential barging.
     
    27912963}
    27922964\end{cfa}
    2793 This routine is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
     2965This function is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
    27942966However, once clusters are fully implemented, it will be possible to create fibers and \textbf{uthread} in the same system, as in listing \ref{f:fiber-uthread}
    27952967\begin{figure}
     
    29763148For monitors, the simplest approach is to measure how long it takes to enter and leave a monitor routine.
    29773149Figure~\ref{f:mutex} shows the code for \CFA.
    2978 To put the results in context, the cost of entering a non-inline routine and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
     3150To put the results in context, the cost of entering a non-inline function and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
    29793151The results can be shown in table \ref{tab:mutex}.
    29803152
     
    32273399Therefore, there is still significant work to improve performance.
    32283400Many of the data structures and algorithms may change in the future to more efficient versions.
    3229 For example, the number of monitors in a single bulk acquire is only bound by the stack size, this is probably unnecessarily generous.
     3401For example, the number of monitors in a single \textbf{bulk-acq} is only bound by the stack size, this is probably unnecessarily generous.
    32303402It may be possible that limiting the number helps increase performance.
    32313403However, it is not obvious that the benefit would be significant.
  • doc/papers/concurrency/figures/ext_monitor.fig

    rb21c77a r97397a26  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1575.000 3450.000 1575 3150 1275 3450 1575 3750
    11 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1575.000 4350.000 1575 4050 1275 4350 1575 4650
    12 6 4275 1950 4575 2250
    13 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2100 105 105 4425 2100 4530 2205
    14 4 1 -1 0 0 0 10 0.0000 2 105 90 4425 2160 d\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 3450.000 3150 3150 2850 3450 3150 3750
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 4350.000 3150 4050 2850 4350 3150 4650
     126 5850 1950 6150 2250
     131 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2100 105 105 6000 2100 6105 2205
     144 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
    1515-6
    16 6 4275 1650 4575 1950
    17 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 1800 105 105 4425 1800 4530 1905
    18 4 1 -1 0 0 0 10 0.0000 2 105 90 4425 1860 b\001
     166 5100 2100 5400 2400
     171 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
     184 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
    1919-6
    20 6 1495 5445 5700 5655
    21 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1575 5550 80 80 1575 5550 1655 5630
    22 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 5550 105 105 2925 5550 3030 5655
    23 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4425 5550 105 105 4425 5550 4530 5655
    24 4 0 -1 0 0 0 12 0.0000 2 135 1035 3150 5625 blocked task\001
    25 4 0 -1 0 0 0 12 0.0000 2 135 870 1725 5625 active task\001
    26 4 0 -1 0 0 0 12 0.0000 2 135 1050 4650 5625 routine mask\001
     206 5100 1800 5400 2100
     211 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 1950 105 105 5250 1950 5355 1950
     224 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
    2723-6
    28 6 3525 1800 3825 2400
    29 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3675 1950 105 105 3675 1950 3780 1950
     246 5850 1650 6150 1950
     251 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
     264 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     27-6
     286 3070 5445 7275 5655
     291 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
     301 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
     311 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 6000 5550 105 105 6000 5550 6105 5655
     324 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
     334 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
     344 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
     35-6
     361 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
     371 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 3600 105 105 3600 3600 3705 3705
     381 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 3900 105 105 6600 3900 6705 4005
     391 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 3900 105 105 6900 3900 7005 4005
     401 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2700 105 105 6000 2700 6105 2805
     411 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2400 105 105 6000 2400 6105 2505
     421 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 5100 4575 80 80 5100 4575 5180 4655
    30432 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    31          3525 1800 3825 1800 3825 2400 3525 2400 3525 1800
    32 4 1 4 0 0 0 10 0.0000 2 105 120 3675 2010 Y\001
    33 -6
    34 6 3525 2100 3825 2400
    35 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3675 2250 105 105 3675 2250 3780 2250
    36 4 1 4 0 0 0 10 0.0000 2 105 120 3675 2295 X\001
    37 -6
    38 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1725 3600 105 105 1725 3600 1830 3705
    39 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2025 3600 105 105 2025 3600 2130 3705
    40 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5025 3900 105 105 5025 3900 5130 4005
    41 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5325 3900 105 105 5325 3900 5430 4005
    42 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2700 105 105 4425 2700 4530 2805
    43 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2400 105 105 4425 2400 4530 2505
    44 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3525 4575 80 80 3525 4575 3605 4655
     44         4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
     452 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     46         3150 3750 3750 3750 3750 4050 3150 4050
     472 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     48         3150 3450 3750 3450 3900 3675
     492 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     50         3750 3150 3600 3375
     512 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     52         3150 4350 3750 4350 3900 4575
     532 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     54         3750 4050 3600 4275
     552 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     56         3150 4650 3750 4650 3750 4950 4950 4950
     572 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     58         6450 3750 6300 3975
     592 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     60         4950 4950 5175 5100
     612 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
     62         5250 4950 6450 4950 6450 4050 7050 4050 7050 3750 6450 3750
     63         6450 2850 6150 2850 6150 1650
     642 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
     65         5850 4200 5850 3300 4350 3300 4350 4200 5850 4200
     662 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
     67        1 1 1.00 60.00 120.00
     68        7 1 1.00 60.00 120.00
     69         5250 3150 5250 2400
     702 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     71         3150 3150 3750 3150 3750 2850 5700 2850 5700 1650
     722 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     73         5700 2850 6150 3000
    45742 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    46          2475 2925 3900 2925 3900 3225 2475 3225 2475 2925
    47 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    48          1575 3750 2175 3750 2175 4050 1575 4050
    49 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    50          1575 3450 2175 3450 2325 3675
    51 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    52          2175 3150 2025 3375
    53 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    54          1575 4350 2175 4350 2325 4575
    55 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    56          2175 4050 2025 4275
    57 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    58          1575 4650 2175 4650 2175 4950 3375 4950
    59 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    60          4875 3750 4725 3975
    61 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    62          3375 4950 3600 5100
    63 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
    64          3675 4950 4875 4950 4875 4050 5475 4050 5475 3750 4875 3750
    65          4875 2850 4575 2850 4575 1650
    66 2 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    67          4275 4200 4275 3300 2775 3300 2775 4200 4275 4200
    68 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    69         1 1 1.00 60.00 120.00
    70          3675 3075 3675 2400
    71 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    72          4125 2850 4575 3000
    73 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    74          1575 3150 2175 3150 2175 2850 4125 2850 4125 1650
    75 4 1 -1 0 0 0 10 0.0000 2 75 75 4425 2745 a\001
    76 4 1 -1 0 0 0 10 0.0000 2 75 75 4425 2445 c\001
    77 4 1 -1 0 0 0 12 0.0000 2 135 315 3525 5325 exit\001
    78 4 1 -1 0 0 0 12 0.0000 2 135 135 1725 3075 A\001
    79 4 1 -1 0 0 0 12 0.0000 2 135 795 1725 4875 condition\001
    80 4 1 -1 0 0 0 12 0.0000 2 135 135 1725 5100 B\001
    81 4 0 -1 0 0 0 12 0.0000 2 135 420 5025 3675 stack\001
    82 4 0 -1 0 0 0 12 0.0000 2 180 750 5025 3225 acceptor/\001
    83 4 0 -1 0 0 0 12 0.0000 2 180 750 5025 3450 signalled\001
    84 4 1 -1 0 0 0 12 0.0000 2 135 795 1725 2850 condition\001
    85 4 1 -1 0 0 0 12 0.0000 2 165 420 4425 1350 entry\001
    86 4 1 -1 0 0 0 12 0.0000 2 135 495 4425 1575 queue\001
    87 4 0 -1 0 0 0 12 0.0000 2 135 525 4725 2400 arrival\001
    88 4 0 -1 0 0 0 12 0.0000 2 135 630 4725 2175 order of\001
    89 4 1 -1 0 0 0 12 0.0000 2 135 525 3525 3675 shared\001
    90 4 1 -1 0 0 0 12 0.0000 2 135 735 3525 3975 variables\001
    91 4 0 4 50 -1 0 11 0.0000 2 120 135 4150 1875 Y\001
    92 4 0 4 50 -1 0 11 0.0000 2 120 105 4150 2175 Z\001
    93 4 0 4 50 -1 0 11 0.0000 2 120 135 4150 2475 X\001
    94 4 0 4 50 -1 0 11 0.0000 2 120 165 4150 2775 W\001
    95 4 0 -1 0 0 3 12 0.0000 2 150 540 5025 4275 urgent\001
    96 4 1 0 50 -1 0 11 0.0000 2 165 600 3150 3150 accepted\001
     75         5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
     764 1 -1 0 0 0 10 0.0000 2 75 75 6000 2745 a\001
     774 1 -1 0 0 0 10 0.0000 2 75 75 6000 2445 c\001
     784 1 -1 0 0 0 12 0.0000 2 135 315 5100 5325 exit\001
     794 1 -1 0 0 0 12 0.0000 2 135 135 3300 3075 A\001
     804 1 -1 0 0 0 12 0.0000 2 135 795 3300 4875 condition\001
     814 1 -1 0 0 0 12 0.0000 2 135 135 3300 5100 B\001
     824 0 -1 0 0 0 12 0.0000 2 135 420 6600 3675 stack\001
     834 0 -1 0 0 0 12 0.0000 2 180 750 6600 3225 acceptor/\001
     844 0 -1 0 0 0 12 0.0000 2 180 750 6600 3450 signalled\001
     854 1 -1 0 0 0 12 0.0000 2 135 795 3300 2850 condition\001
     864 1 -1 0 0 0 12 0.0000 2 165 420 6000 1350 entry\001
     874 1 -1 0 0 0 12 0.0000 2 135 495 6000 1575 queue\001
     884 0 -1 0 0 0 12 0.0000 2 135 525 6300 2400 arrival\001
     894 0 -1 0 0 0 12 0.0000 2 135 630 6300 2175 order of\001
     904 1 -1 0 0 0 12 0.0000 2 135 525 5100 3675 shared\001
     914 1 -1 0 0 0 12 0.0000 2 135 735 5100 3975 variables\001
     924 0 0 50 -1 0 11 0.0000 2 165 855 4275 3150 Acceptables\001
     934 0 0 50 -1 0 11 0.0000 2 120 165 5775 2700 W\001
     944 0 0 50 -1 0 11 0.0000 2 120 135 5775 2400 X\001
     954 0 0 50 -1 0 11 0.0000 2 120 105 5775 2100 Z\001
     964 0 0 50 -1 0 11 0.0000 2 120 135 5775 1800 Y\001
  • doc/papers/concurrency/figures/monitor.fig

    rb21c77a r97397a26  
    72722 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    7373         3600 1500 3600 2100 4200 2100 4200 900
     742 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     75         2700 1500 2700 2100 3300 2100 3300 1500
    74762 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
    7577         3600 4200 4800 4200 4800 3300 5400 3300 5400 3000 4800 3000
     
    77792 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    7880         4200 3450 4200 2550 2700 2550 2700 3450 4200 3450
    79 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    80          2700 1500 2700 2100 3300 2100 3300 1500
    81814 1 -1 0 0 0 10 0.0000 2 75 75 4350 1995 a\001
    82824 1 -1 0 0 0 10 0.0000 2 75 75 4350 1695 c\001
     
    89894 0 -1 0 0 0 12 0.0000 2 180 750 4950 2700 signalled\001
    90904 1 -1 0 0 0 12 0.0000 2 135 795 1650 2100 condition\001
    91 4 1 4 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
    92 4 1 4 0 0 0 12 0.0000 2 135 135 3450 1425 Y\001
     914 1 -1 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
     924 1 -1 0 0 0 12 0.0000 2 135 135 3450 1425 Y\001
    93934 1 -1 0 0 0 12 0.0000 2 165 420 4350 600 entry\001
    94944 1 -1 0 0 0 12 0.0000 2 135 495 4350 825 queue\001
     
    1001004 1 -1 0 0 0 10 0.0000 2 75 75 3450 1995 c\001
    1011014 1 -1 0 0 0 12 0.0000 2 135 570 3000 1200 queues\001
    102 4 0 -1 0 0 3 12 0.0000 2 150 540 4950 3525 urgent\001
  • doc/papers/general/Makefile

    rb21c77a r97397a26  
    5959        dvips ${Build}/$< -o $@
    6060
    61 ${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 ../../bibliography/pl.bib | ${Build}
     61${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                ../../bibliography/pl.bib
    6363        # Must have *.aux file containing citations for bibtex
    6464        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    7575        mkdir -p ${Build}
    7676
    77 ${BASE}.out.ps : | ${Build}
     77${BASE}.out.ps : ${Build}
    7878        ln -fs ${Build}/Paper.out.ps .
    7979
     
    8484        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    8585
    86 %.tex : %.fig | ${Build}
     86%.tex : %.fig ${Build}
    8787        fig2dev -L eepic $< > ${Build}/$@
    8888
    89 %.ps : %.fig | ${Build}
     89%.ps : %.fig ${Build}
    9090        fig2dev -L ps $< > ${Build}/$@
    9191
    92 %.pstex : %.fig | ${Build}
     92%.pstex : %.fig ${Build}
    9393        fig2dev -L pstex $< > ${Build}/$@
    9494        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/general/Paper.tex

    rb21c77a r97397a26  
    201201
    202202\abstract[Summary]{
    203 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating-systems.
     203The 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.
    204204This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    205205Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive.
     
    224224\section{Introduction}
    225225
    226 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating-systems.
     226The 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.
    227227This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    228228The TIOBE~\cite{TIOBE} ranks the top 5 most \emph{popular} programming languages as: Java 15\%, \Textbf{C 12\%}, \Textbf{\CC 5.5\%}, Python 5\%, \Csharp 4.5\% = 42\%, where the next 50 languages are less than 4\% each with a long tail.
  • doc/proposals/ctordtor/Makefile

    rb21c77a r97397a26  
    1 ## Define the configuration variables.
     1## Define the appropriate configuration variables.
    22
    3 Build = build
    4 Figures = figures
    5 Macros = ../../LaTeXmacros
    6 Bib = ../../bibliography
     3MACROS = ../../LaTeXmacros
     4BIB = ../../bibliography
    75
    8 TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
    9 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
     6TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
     7LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
    108BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    11 
    12 MAKEFLAGS = --no-print-directory # --silent
    13 VPATH = ${Build} ${Figures}
    149
    1510## Define the text source files.
     
    3429
    3530DOCUMENT = ctor.pdf
    36 BASE = ${basename ${DOCUMENT}}
    3731
    3832# Directives #
    39 
    40 .PHONY : all clean                                      # not file names
    4133
    4234all : ${DOCUMENT}
    4335
    4436clean :
    45         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     37        rm -f *.bbl *.aux *.dvi *.idx *.ilg *.ind *.brf *.out *.log *.toc *.blg *.pstex_t *.cf \
     38                ${FIGURES} ${PICTURES} ${PROGRAMS} ${GRAPHS} ${basename ${DOCUMENT}}.ps ${DOCUMENT}
    4639
    4740# File Dependencies #
    4841
    49 ${DOCUMENT} : ${BASE}.ps
     42${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    5043        ps2pdf $<
    5144
    52 ${BASE}.ps : ${BASE}.dvi
    53         dvips ${Build}/$< -o $@
     45${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     46        dvips $< -o $@
    5447
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
     48${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
     49                $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
    5750        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    58         #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     51        if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
    5952        # Must have *.aux file containing citations for bibtex
    6053        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    61         -${BibTeX} ${Build}/${basename $@}
    62         # Some citations reference others so run again to resolve these citations
     54        -${BibTeX} ${basename $@}
     55        # Some citations reference others so run steps again to resolve these citations
    6356        ${LaTeX} ${basename $@}.tex
    64         -${BibTeX} ${Build}/${basename $@}
     57        -${BibTeX} ${basename $@}
    6558        # Make index from *.aux entries and input index at end of document
    66         #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
    67         # Run again to finish citations
     59        makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
    6860        ${LaTeX} ${basename $@}.tex
    6961        # Run again to get index title into table of contents
     
    7567## Define the default recipes.
    7668
    77 ${Build}:
    78         mkdir -p ${Build}
     69%.tex : %.fig
     70        fig2dev -L eepic $< > $@
    7971
    80 %.tex : %.fig | ${Build}
    81         fig2dev -L eepic $< > ${Build}/$@
     72%.ps : %.fig
     73        fig2dev -L ps $< > $@
    8274
    83 %.ps : %.fig | ${Build}
    84         fig2dev -L ps $< > ${Build}/$@
    85 
    86 %.pstex : %.fig | ${Build}
    87         fig2dev -L pstex $< > ${Build}/$@
    88         fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     75%.pstex : %.fig
     76        fig2dev -L pstex $< > $@
     77        fig2dev -L pstex_t -p $@ $< > $@_t
    8978
    9079# Local Variables: #
  • doc/proposals/ctordtor/ctor.tex

    rb21c77a r97397a26  
     1% inline code ©...© (copyright symbol) emacs: C-q M-)
     2% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     3% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
     4% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
     5% LaTex escape §...§ (section symbol) emacs: C-q M-'
     6% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     7% math escape $...$ (dollar symbol)
     8
    19\documentclass[twoside,11pt]{article}
    210
     
    715\usepackage{textcomp}
    816\usepackage[latin1]{inputenc}
    9 
    1017\usepackage{fullpage,times,comment}
    1118\usepackage{epic,eepic}
    12 \usepackage{upquote}                                    % switch curled `'" to straight
     19\usepackage{upquote}                                                                    % switch curled `'" to straight
    1320\usepackage{calc}
    1421\usepackage{xspace}
    1522\usepackage{graphicx}
    16 \usepackage{varioref}                                   % extended references
    17 \usepackage{listings}                                   % format program code
    18 \usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
     23\usepackage{varioref}                                                                   % extended references
     24\usepackage{listings}                                                                   % format program code
     25\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    1926\usepackage{latexsym}                                   % \Box glyph
    2027\usepackage{mathptmx}                                   % better math font with "times"
     
    2734\renewcommand{\UrlFont}{\small\sf}
    2835
    29 \setlength{\topmargin}{-0.45in}                         % move running title into header
     36\setlength{\topmargin}{-0.45in}                                                 % move running title into header
    3037\setlength{\headsep}{0.25in}
    3138
     
    3643
    3744\interfootnotelinepenalty=10000
    38 
    39 \CFAStyle                                               % use default CFA format-style
    40 % inline code ©...© (copyright symbol) emacs: C-q M-)
    41 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    42 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    43 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    44 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    45 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    46 % math escape $...$ (dollar symbol)
    47 
    4845
    4946\title{
     
    8683\thispagestyle{plain}
    8784\pagenumbering{arabic}
     85
    8886
    8987
  • doc/proposals/tuples/Makefile

    rb21c77a r97397a26  
    1 ## Define the configuration variables.
     1## Define the appropriate configuration variables.
    22
    3 Build = build
    4 Figures = figures
    5 Macros = ../../LaTeXmacros
    6 Bib = ../../bibliography
     3MACROS = ../../LaTeXmacros
     4BIB = ../../bibliography
    75
    8 TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
    9 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
     6TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
     7LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
    108BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    11 
    12 MAKEFLAGS = --no-print-directory --silent #
    13 VPATH = ${Build} ${Figures}
    149
    1510## Define the text source files.
     
    3429
    3530DOCUMENT = tuples.pdf
    36 BASE = ${basename ${DOCUMENT}}
    3731
    3832# Directives #
    39 
    40 .PHONY : all clean                                      # not file names
    4133
    4234all : ${DOCUMENT}
    4335
    4436clean :
    45         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     37        rm -f *.bbl *.aux *.dvi *.idx *.ilg *.ind *.brf *.out *.log *.toc *.blg *.pstex_t *.cf \
     38                ${FIGURES} ${PICTURES} ${PROGRAMS} ${GRAPHS} ${basename ${DOCUMENT}}.ps ${DOCUMENT}
    4639
    4740# File Dependencies #
    4841
    49 ${DOCUMENT} : ${BASE}.ps
     42${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    5043        ps2pdf $<
    5144
    52 ${BASE}.ps : ${BASE}.dvi
    53         dvips ${Build}/$< -o $@
     45${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     46        dvips $< -o $@
    5447
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
     48${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
     49                $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
    5750        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    58         #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     51        if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
    5952        # Must have *.aux file containing citations for bibtex
    6053        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    61         -${BibTeX} ${Build}/${basename $@}
    62         # Some citations reference others so run again to resolve these citations
     54        -${BibTeX} ${basename $@}
     55        # Some citations reference others so run steps again to resolve these citations
    6356        ${LaTeX} ${basename $@}.tex
    64         -${BibTeX} ${Build}/${basename $@}
     57        -${BibTeX} ${basename $@}
    6558        # Make index from *.aux entries and input index at end of document
    66         #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
    67         # Run again to finish citations
     59        makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
    6860        ${LaTeX} ${basename $@}.tex
    6961        # Run again to get index title into table of contents
     
    7567## Define the default recipes.
    7668
    77 ${Build}:
    78         mkdir -p ${Build}
     69%.tex : %.fig
     70        fig2dev -L eepic $< > $@
    7971
    80 %.tex : %.fig | ${Build}
    81         fig2dev -L eepic $< > ${Build}/$@
     72%.ps : %.fig
     73        fig2dev -L ps $< > $@
    8274
    83 %.ps : %.fig | ${Build}
    84         fig2dev -L ps $< > ${Build}/$@
    85 
    86 %.pstex : %.fig | ${Build}
    87         fig2dev -L pstex $< > ${Build}/$@
    88         fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     75%.pstex : %.fig
     76        fig2dev -L pstex $< > $@
     77        fig2dev -L pstex_t -p $@ $< > $@_t
    8978
    9079# Local Variables: #
  • doc/proposals/tuples/tuples.tex

    rb21c77a r97397a26  
     1% inline code ©...© (copyright symbol) emacs: C-q M-)
     2% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     3% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
     4% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
     5% LaTex escape §...§ (section symbol) emacs: C-q M-'
     6% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     7% math escape $...$ (dollar symbol)
     8
    19\documentclass[twoside,11pt]{article}
    210
     
    715\usepackage{textcomp}
    816\usepackage[latin1]{inputenc}
    9 
    1017\usepackage{fullpage,times,comment}
    1118\usepackage{epic,eepic}
    12 \usepackage{upquote}                                    % switch curled `'" to straight
     19\usepackage{upquote}                                                                    % switch curled `'" to straight
    1320\usepackage{calc}
    1421\usepackage{xspace}
    1522\usepackage{graphicx}
    16 \usepackage{varioref}                                   % extended references
    17 \usepackage{listings}                                   % format program code
    18 \usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
     23\usepackage{varioref}                                                                   % extended references
     24\usepackage{listings}                                                                   % format program code
     25\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    1926\usepackage{latexsym}                                   % \Box glyph
    2027\usepackage{mathptmx}                                   % better math font with "times"
     
    2734\renewcommand{\UrlFont}{\small\sf}
    2835
    29 \setlength{\topmargin}{-0.45in}                         % move running title into header
     36\setlength{\topmargin}{-0.45in}                                                 % move running title into header
    3037\setlength{\headsep}{0.25in}
    3138
     
    3542
    3643\interfootnotelinepenalty=10000
    37 
    38 \CFAStyle                                               % use default CFA format-style
    39 % inline code ©...© (copyright symbol) emacs: C-q M-)
    40 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    41 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    42 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    43 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    44 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    45 % math escape $...$ (dollar symbol)
    46 
    4744
    4845\title{
  • doc/proposals/user_conversions.md

    rb21c77a r97397a26  
    55There is also a set of _explicit_ conversions that are only allowed through a
    66cast expression.
    7 I propose that safe, unsafe, and explicit (cast) conversions be expressed as
    8 constructor variants.
     7Based on Glen's notes on conversions [1], I propose that safe and unsafe
     8conversions be expressed as constructor variants, though I make explicit
     9(cast) conversions a constructor variant as well rather than a dedicated
     10operator.
    911Throughout this article, I will use the following operator names for
    1012constructors and conversion functions from `From` to `To`:
    1113
    12         void ?{} ( To&, To );            // copy constructor
    13         void ?{} ( To&, From );          // explicit constructor
    14         void ?{explicit} ( To&, From );  // explicit cast conversion
    15         void ?{safe} ( To&, From );      // implicit safe conversion
    16         void ?{unsafe} ( To&, From );    // implicit unsafe conversion
    17 
    18 It has been suggested that all constructors would define unsafe implicit
     14        void ?{} ( To*, To );            // copy constructor
     15        void ?{} ( To*, From );          // explicit constructor
     16        void ?{explicit} ( To*, From );  // explicit cast conversion
     17        void ?{safe} ( To*, From );      // implicit safe conversion
     18        void ?{unsafe} ( To*, From );    // implicit unsafe conversion
     19
     20[1] http://plg.uwaterloo.ca/~cforall/Conversions/index.html
     21
     22Glen's design made no distinction between constructors and unsafe implicit
    1923conversions; this is elegant, but interacts poorly with tuples.
    2024Essentially, without making this distinction, a constructor like the following
     
    2226multiplying the space of possible interpretations of all functions:
    2327
    24         void ?{}( Coord& this, int x, int y );
     28        void ?{}( Coord *this, int x, int y );
    2529
    2630That said, it would certainly be possible to make a multiple-argument implicit
     
    2832used infrequently:
    2933
    30         void ?{unsafe}( Coord& this, int x, int y );
     34        void ?{unsafe}( Coord *this, int x, int y );
    3135
    3236An alternate possibility would be to only count two-arg constructors
    33 `void ?{} ( To&, From )` as unsafe conversions; under this semantics, safe and
     37`void ?{} ( To*, From )` as unsafe conversions; under this semantics, safe and
    3438explicit conversions should also have a compiler-enforced restriction to
    3539ensure that they are two-arg functions (this restriction may be valuable
     
    3943is convertable to `To`.
    4044If user-defined conversions are not added to the language,
    41 `void ?{} ( To&, From )` may be a suitable representation, relying on
     45`void ?{} ( To*, From )` may be a suitable representation, relying on
    4246conversions on the argument types to account for transitivity.
    43 Since `To&` should be an exact match on `To`, this should put all the implicit
    44 conversions on the RHS.
    45 On the other hand, under some models (like [1]), implicit conversions are not
    46 allowed in assertion parameters, so another assertion syntax specific to
    47 conversions may be required, e.g. `From -> To`.
    48 It has also been suggested that, for programmer control, no implicit
    49 conversions (except, possibly, for polymorphic specialization) should be
    50 allowed in resolution of cast operators.
    51 
    52 [1] ../working/assertion_resolution.md
     47On the other hand, `To*` should perhaps match its target type exactly, so
     48another assertion syntax specific to conversions may be required, e.g.
     49`From -> To`.
    5350
    5451### Constructor Idiom ###
     
    5653that we can use the full range of Cforall features for conversions, including
    5754polymorphism.
    58 In an earlier version of this proposal, Glen Ditchfield defines a
    59 _constructor idiom_ that can be used to create chains of safe conversions
    60 without duplicating code; given a type `Safe` which members of another type
    61 `From` can be directly converted to, the constructor idiom allows us to write
    62 a conversion for any type `To` which `Safe` converts to:
    63 
    64         forall(otype To | { void ?{safe}( To&, Safe ) })
    65         void ?{safe}( To& this, From that ) {
     55Glen [1] defines a _constructor idiom_ that can be used to create chains of
     56safe conversions without duplicating code; given a type `Safe` which members
     57of another type `From` can be directly converted to, the constructor idiom
     58allows us to write a conversion for any type `To` which `Safe` converts to:
     59
     60        forall(otype To | { void ?{safe}( To*, Safe ) })
     61        void ?{safe}( To *this, From that ) {
    6662                Safe tmp = /* some expression involving that */;
    67                 this{ tmp }; // initialize from assertion parameter
     63                *this = tmp; // uses assertion parameter
    6864        }
    6965
     
    7167unsafe conversions.
    7268
    73 Glen's original suggestion said the copy constructor for `To` should also be
    74 accepted as a resolution for `void ?{safe}( To&, Safe )` (`Safe` == `To`),
    75 allowing this same code to be used for the single-step conversion as well.
    76 This proposal does come at the cost of an extra copy initialization of the
    77 target value, though.
    78 
    79 Contrariwise, if a monomorphic conversion from `From` to `Safe` is written,
    80 e.g:
    81 
    82         void ?{safe}( Safe& this, From that ) {
    83                 this{ /* some parameters involving that */ };
    84         }
    85 
    86 Then the code for a transitive conversion from `From` to any `To` type
    87 convertable from `Safe` is written:
    88 
    89         forall(otype To | { void ?{safe}( To&, Safe ) })
    90         void ?{safe}( To& this, From that ) {
    91                 Safe tmp = that;  // uses monomorphic conversion
    92                 this{ tmp };      // initialize from assertion parameter
    93         }
    94 
    95 Given the entirely-boilerplate nature of this code, but negative performance
    96 implications of the unmodified constructor idiom, it might be fruitful to have
    97 transitive and single step conversion operators, and let CFA build the
    98 transitive conversions; some possible names:
    99 
    100         void ?{safe}  (To&, From);    void ?{final safe} (To&, From);  // single-step
    101         void ?{safe*} (To&, From);    void ?{safe}       (To&, From);  // transitive
    102 
    10369What selective non-use of the constructor idiom gives us is the ability to
    10470define a conversion that may only be the *last* conversion in a chain of such.
    105 One use for this is to solve the problem that `explicit` conversions were
    106 added to C++ for, that of conversions to `bool` chaining to become conversions
    107 to any arithmetic type.
    108 Another use is to unambiguously represent the full hierarchy of implicit
    109 conversions in C by making sign conversions non-transitive, allowing the
    110 compiler to resolve e.g. `int -> unsigned long` as
    111 `int -> long -> unsigned long` over `int -> unsigned int -> unsigned long`.
    112 See [2] for more details.
    113 
    114 [2] ../working/glen_conversions/index.html#usual
     71Constructing a conversion graph able to unambiguously represent the full
     72hierarchy of implicit conversions in C is provably impossible using only
     73single-step conversions with no additional information (see Appendix A), but
     74this mechanism is sufficiently powerful (see [1], though the design there has
     75some minor bugs; the general idea is to use the constructor idiom to define
     76two chains of conversions, one among the signed integral types, another among
     77the unsigned, and to use monomorphic conversions to allow conversions between
     78signed and unsigned integer types).
    11579
    11680### Appendix A: Partial and Total Orders ###
     
    189153convert from `int` to `unsigned long`, so we just put in a direct conversion
    190154and make the compiler smart enough to figure out the costs" - this is the
    191 approach taken by the existing compiler, but given that in a user-defined
     155approach taken by the existing compipler, but given that in a user-defined
    192156conversion proposal the users can build an arbitrary graph of conversions,
    193157this case still needs to be handled.
     
    196160exists a chain of conversions from `a` to `b` (see Appendix A for description
    197161of preorders and related constructs).
    198 This preorder roughly corresponds to a more usual type-theoretic concept of
     162This preorder corresponds roughly to a more usual type-theoretic concept of
    199163subtyping ("if I can convert `a` to `b`, `a` is a more specific type than
    200164`b`"); however, since this graph is arbitrary, it may contain cycles, so if
     
    228192and so is considered to be the nearer type.
    229193By transitivity, then, the conversion from `X` to `Y2` should be cheaper than
    230 the conversion from `X` to `W`, but in this case the `Y2` and `W` are
     194the conversion from `X` to `W`, but in this case the `X` and `W` are
    231195incomparable by the conversion preorder, so the tie is broken by the shorter
    232196path from `X` to `W` in favour of `W`, contradicting the transitivity property
  • doc/refrat/Makefile

    rb21c77a r97397a26  
    5353        dvips ${Build}/$< -o $@
    5454
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
     55${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
    5757        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    5858        if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     
    7878        mkdir -p ${Build}
    7979
    80 %.tex : %.fig | ${Build}
     80%.tex : %.fig ${Build}
    8181        fig2dev -L eepic $< > ${Build}/$@
    8282
    83 %.ps : %.fig | ${Build}
     83%.ps : %.fig ${Build}
    8484        fig2dev -L ps $< > ${Build}/$@
    8585
    86 %.pstex : %.fig | ${Build}
     86%.pstex : %.fig ${Build}
    8787        fig2dev -L pstex $< > ${Build}/$@
    8888        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/theses/aaron_moss/comp_II/Makefile

    rb21c77a r97397a26  
    3232
    3333DOCUMENT = comp_II.pdf
    34 BASE = ${basename ${DOCUMENT}}
    3534
    3635# Directives #
     
    4140
    4241clean :
    43         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     42        @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
    4443
    4544# File Dependencies #
    4645
    47 ${DOCUMENT} : ${BASE}.ps
     46${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    4847        ps2pdf $<
    4948
    50 ${BASE}.ps : ${BASE}.dvi
     49${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    5150        dvips ${Build}/$< -o $@
    5251
    53 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    54                 ${Macros}/common.tex ${Macros}/indexstyle ../../../bibliography/pl.bib | ${Build}
     52${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     53                ${Macros}/common.tex ${Macros}/indexstyle ../../../bibliography/pl.bib
    5554        # Must have *.aux file containing citations for bibtex
    5655        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6766        mkdir -p ${Build}
    6867
    69 %.tex : %.fig ${Build}
     68%.tex : %.fig
    7069        fig2dev -L eepic $< > ${Build}/$@
    7170
    72 %.ps : %.fig | ${Build}
     71%.ps : %.fig
    7372        fig2dev -L ps $< > ${Build}/$@
    7473
    75 %.pstex : %.fig | ${Build}
     74%.pstex : %.fig
    7675        fig2dev -L pstex $< > ${Build}/$@
    7776        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/theses/thierry_delisle/.gitignore

    rb21c77a r97397a26  
    2525*.pdf
    2626*.png
    27 *.ps
    2827figures/*.tex
    2928
  • doc/theses/thierry_delisle/Makefile

    rb21c77a r97397a26  
    5151
    5252DOCUMENT = thesis.pdf
    53 BASE = ${basename ${DOCUMENT}}
    5453
    5554# Directives #
     
    6059
    6160clean :
    62         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     61        @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
    6362
    6463# File Dependencies #
    6564
    66 ${DOCUMENT} : ${BASE}.ps
     65${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    6766        ps2pdf $<
    6867
    69 ${BASE}.ps : ${BASE}.dvi
     68${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    7069        dvips ${Build}/$< -o $@
    7170
    72 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    73                 ${Macros}/common.tex ${Macros}/indexstyle annex/local.bib ../../bibliography/pl.bib | ${Build}
     71${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     72                ${Macros}/common.tex ${Macros}/indexstyle annex/local.bib ../../bibliography/pl.bib
    7473        # Must have *.aux file containing citations for bibtex
    7574        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    8988        mkdir -p ${Build}
    9089
    91 %.tex : %.fig ${Build}
     90%.tex : %.fig
    9291        fig2dev -L eepic $< > ${Build}/$@
    9392
    94 %.ps : %.fig | ${Build}
     93%.ps : %.fig
    9594        fig2dev -L ps $< > ${Build}/$@
    9695
    97 %.pstex : %.fig | ${Build}
     96%.pstex : %.fig
    9897        fig2dev -L pstex $< > ${Build}/$@
    9998        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     
    102101# Tools to generate png files
    103102# to create a png we create a pdf and convert it to png
    104 %.png : build/%.pstex figures/%.tex ${Build}
     103%.png : build/%.pstex figures/%.tex
    105104        echo ${basename $@}
    106105        ${LaTeX} figures/${basename $@}.tex
     
    110109
    111110# creating a pdf of a figure requires generating some latex that just includes the figure
    112 figures/%.tex: build/%.pstex ${Build}
     111figures/%.tex: build/%.pstex
    113112        echo -n         "\documentclass[preview]{standalone}\n"         \
    114113                        "\usepackage[T1]{fontenc}\n"                    \
  • doc/user/Makefile

    rb21c77a r97397a26  
    5757        dvips ${Build}/$< -o $@
    5858
    59 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    60                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
     59${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     60                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
    6161        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    6262        if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     
    7979        mkdir -p ${Build}
    8080
    81 %.tex : %.fig | ${Build}
     81%.tex : %.fig ${Build}
    8282        fig2dev -L eepic $< > ${Build}/$@
    8383
    84 %.ps : %.fig | ${Build}
     84%.ps : %.fig ${Build}
    8585        fig2dev -L ps $< > ${Build}/$@
    8686
    87 %.pstex : %.fig | ${Build}
     87%.pstex : %.fig ${Build}
    8888        fig2dev -L pstex $< > ${Build}/$@
    8989        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • src/CodeGen/CodeGenerator.cc

    rb21c77a r97397a26  
    133133                output << "__attribute__ ((";
    134134                for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
    135                         output << (*attr)->name;
    136                         if ( ! (*attr)->parameters.empty() ) {
     135                        output << (*attr)->get_name();
     136                        if ( ! (*attr)->get_parameters().empty() ) {
    137137                                output << "(";
    138                                 genCommaList( (*attr)->parameters.begin(), (*attr)->parameters.end() );
     138                                genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
    139139                                output << ")";
    140140                        } // if
     
    172172        // *** Declarations
    173173        void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
    174                 // deleted decls should never be used, so don't print them
    175                 if ( functionDecl->isDeleted && genC ) return;
    176174                extension( functionDecl );
    177175                genAttributes( functionDecl->get_attributes() );
     
    187185                        functionDecl->get_statements()->accept( *visitor );
    188186                } // if
    189                 if ( functionDecl->isDeleted ) {
    190                         output << " = void";
    191                 }
    192187        }
    193188
    194189        void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
    195                 // deleted decls should never be used, so don't print them
    196                 if ( objectDecl->isDeleted && genC ) return;
    197190                if (objectDecl->get_name().empty() && genC ) {
    198191                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
     
    213206                        objectDecl->get_init()->accept( *visitor );
    214207                } // if
    215                 if ( objectDecl->isDeleted ) {
    216                         output << " = void";
    217                 }
    218208
    219209                if ( objectDecl->get_bitfieldWidth() ) {
     
    837827                expr->expr->accept( *visitor );
    838828        }
    839 
    840         void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
    841                 assertf( ! genC, "Default argument expressions should not reach code generation." );
    842                 arg->expr->accept( *visitor );
    843         }
    844 
    845         void CodeGenerator::postvisit( GenericExpr * expr ) {
    846                 assertf( ! genC, "C11 _Generic expressions should not reach code generation." );
    847                 output << "_Generic(";
    848                 expr->control->accept( *visitor );
    849                 output << ", ";
    850                 unsigned int numAssocs = expr->associations.size();
    851                 unsigned int i = 0;
    852                 for ( GenericExpr::Association & assoc : expr->associations ) {
    853                         if (assoc.isDefault) {
    854                                 output << "default: ";
    855                         } else {
    856                                 output << genType( assoc.type, "", pretty, genC ) << ": ";
    857                         }
    858                         assoc.expr->accept( *visitor );
    859                         if ( i+1 != numAssocs ) {
    860                                 output << ", ";
    861                         }
    862                         i++;
    863                 }
    864                 output << ")";
    865         }
    866 
    867829
    868830        // *** Statements
  • src/CodeGen/CodeGenerator.h

    rb21c77a r97397a26  
    9494                void postvisit( ConstructorExpr * );
    9595                void postvisit( DeletedExpr * );
    96                 void postvisit( DefaultArgExpr * );
    97                 void postvisit( GenericExpr * );
    9896
    9997                //*** Statements
  • src/Common/Debug.h

    rb21c77a r97397a26  
    2828namespace Debug {
    2929        /// debug codegen a translation unit
    30         static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Builtin ) {
     30        static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
  • src/Common/PassVisitor.h

    rb21c77a r97397a26  
    125125        virtual void visit( InitExpr *  initExpr ) override final;
    126126        virtual void visit( DeletedExpr *  delExpr ) override final;
    127         virtual void visit( DefaultArgExpr * argExpr ) override final;
    128         virtual void visit( GenericExpr * genExpr ) override final;
    129127
    130128        virtual void visit( VoidType * basicType ) override final;
     
    227225        virtual Expression * mutate( InitExpr *  initExpr ) override final;
    228226        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
    229         virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
    230         virtual Expression * mutate( GenericExpr * genExpr ) override final;
    231227
    232228        virtual Type * mutate( VoidType * basicType ) override final;
     
    262258
    263259private:
    264         bool inFunction = false;
    265 
    266260        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    267261        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     
    319313        void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    320314        void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
    321         void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
     315        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith     ( pass, 0, exprs, withStmt ); }
    322316
    323317
  • src/Common/PassVisitor.impl.h

    rb21c77a r97397a26  
    404404                        indexerAddId( func );
    405405                        maybeAccept_impl( node->type, *this );
    406                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    407                         // a new scope if inFunction is true
    408                         ValueGuard< bool > oldInFunction( inFunction );
    409                         inFunction = true;
    410406                        maybeAccept_impl( node->statements, *this );
    411407                        maybeAccept_impl( node->attributes, *this );
     
    438434                        indexerAddId( func );
    439435                        maybeMutate_impl( node->type, *this );
    440                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    441                         // a new scope if inFunction is true
    442                         ValueGuard< bool > oldInFunction( inFunction );
    443                         inFunction = true;
    444436                        maybeMutate_impl( node->statements, *this );
    445437                        maybeMutate_impl( node->attributes, *this );
     
    720712        VISIT_START( node );
    721713        {
    722                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    723                 ValueGuard< bool > oldInFunction( inFunction );
    724                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     714                auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    725715                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    726                 inFunction = false;
    727716                visitStatementList( node->kids );
    728717        }
     
    734723        MUTATE_START( node );
    735724        {
    736                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    737                 ValueGuard< bool > oldInFunction( inFunction );
    738                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     725                auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    739726                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    740                 inFunction = false;
    741727                mutateStatementList( node->kids );
    742728        }
     
    842828        VISIT_START( node );
    843829
    844         {
    845                 // while statements introduce a level of scope (for the initialization)
    846                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    847                 maybeAccept_impl( node->initialization, *this );
    848                 visitExpression ( node->condition );
    849                 node->body = visitStatement( node->body );
    850         }
     830        visitExpression( node->condition );
     831        node->body = visitStatement( node->body );
    851832
    852833        VISIT_END( node );
     
    857838        MUTATE_START( node );
    858839
    859         {
    860                 // while statements introduce a level of scope (for the initialization)
    861                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    862                 maybeMutate_impl( node->initialization, *this );
    863                 node->condition = mutateExpression( node->condition );
    864                 node->body      = mutateStatement ( node->body      );
    865         }
    866 
     840        node->condition = mutateExpression( node->condition );
     841        node->body      = mutateStatement ( node->body      );
    867842
    868843        MUTATE_END( Statement, node );
     
    20992074
    21002075//--------------------------------------------------------------------------
    2101 // DefaultArgExpr
    2102 template< typename pass_type >
    2103 void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
    2104         VISIT_START( node );
    2105 
    2106         indexerScopedAccept( node->result, *this );
    2107         maybeAccept_impl( node->expr, *this );
    2108 
    2109         VISIT_END( node );
    2110 }
    2111 
    2112 template< typename pass_type >
    2113 Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
    2114         MUTATE_START( node );
    2115 
    2116         indexerScopedMutate( node->env, *this );
    2117         indexerScopedMutate( node->result, *this );
    2118         maybeMutate_impl( node->expr, *this );
    2119 
    2120         MUTATE_END( Expression, node );
    2121 }
    2122 
    2123 //--------------------------------------------------------------------------
    2124 // GenericExpr
    2125 template< typename pass_type >
    2126 void PassVisitor< pass_type >::visit( GenericExpr * node ) {
    2127         VISIT_START( node );
    2128 
    2129         indexerScopedAccept( node->result, *this );
    2130         maybeAccept_impl( node->control, *this );
    2131         for ( GenericExpr::Association & assoc : node->associations ) {
    2132                 indexerScopedAccept( assoc.type, *this );
    2133                 maybeAccept_impl( assoc.expr, *this );
    2134         }
    2135 
    2136         VISIT_END( node );
    2137 }
    2138 
    2139 template< typename pass_type >
    2140 Expression * PassVisitor< pass_type >::mutate( GenericExpr * node ) {
    2141         MUTATE_START( node );
    2142 
    2143         indexerScopedMutate( node->env, *this );
    2144         indexerScopedMutate( node->result, *this );
    2145         maybeMutate_impl( node->control, *this );
    2146         for ( GenericExpr::Association & assoc : node->associations ) {
    2147                 indexerScopedMutate( assoc.type, *this );
    2148                 maybeMutate_impl( assoc.expr, *this );
    2149         }
    2150 
    2151         MUTATE_END( Expression, node );
    2152 }
    2153 
    2154 //--------------------------------------------------------------------------
    21552076// VoidType
    21562077template< typename pass_type >
  • src/Common/SemanticError.cc

    rb21c77a r97397a26  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  7 08:05:26 2018
    13 // Update Count     : 10
     12// Last Modified On : Wed May 16 15:01:20 2018
     13// Update Count     : 9
    1414//
    1515
     
    9797void SemanticError( CodeLocation location, std::string error ) {
    9898        SemanticErrorThrow = true;
    99         throw SemanticErrorException( location, error );
     99        throw SemanticErrorException(location, error);
    100100}
    101101
  • src/Concurrency/Keywords.cc

    rb21c77a r97397a26  
    192192                void postvisit(   StructDecl * decl );
    193193
    194                 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
     194                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
    195195                void validate( DeclarationWithType * );
    196196                void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     
    431431        void MutexKeyword::postvisit(FunctionDecl* decl) {
    432432
    433                 bool first = false;
    434                 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
     433                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
     434                if( mutexArgs.empty() ) return;
     435
     436                if( CodeGen::isConstructor(decl->name) ) SemanticError( decl, "constructors cannot have mutex parameters" );
     437
    435438                bool isDtor = CodeGen::isDestructor( decl->name );
    436439
    437                 // Is this function relevant to monitors
    438                 if( mutexArgs.empty() ) {
    439                         // If this is the destructor for a monitor it must be mutex
    440                         if(isDtor) {
    441                                 Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
    442 
    443                                 // If it's a copy, it's not a mutex
    444                                 ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
    445                                 if( ! rty ) return;
    446 
    447                                 // If we are not pointing directly to a type, it's not a mutex
    448                                 Type* base = rty->get_base();
    449                                 if( dynamic_cast< ReferenceType * >( base ) ) return;
    450                                 if( dynamic_cast< PointerType * >( base ) ) return;
    451 
    452                                 // Check if its a struct
    453                                 StructInstType * baseStruct = dynamic_cast< StructInstType * >( base );
    454                                 if( !baseStruct ) return;
    455 
    456                                 // Check if its a monitor
    457                                 if(baseStruct->baseStruct->is_monitor() || baseStruct->baseStruct->is_thread())
    458                                         SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
    459                         }
    460                         return;
    461                 }
    462 
    463                 // Monitors can't be constructed with mutual exclusion
    464                 if( CodeGen::isConstructor(decl->name) && !first ) SemanticError( decl, "constructors cannot have mutex parameters" );
    465 
    466                 // It makes no sense to have multiple mutex parameters for the destructor
    467440                if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
    468441
    469                 // Make sure all the mutex arguments are monitors
    470442                for(auto arg : mutexArgs) {
    471443                        validate( arg );
    472444                }
    473445
    474                 // Check if we need to instrument the body
    475446                CompoundStmt* body = decl->get_statements();
    476447                if( ! body ) return;
    477448
    478                 // Do we have the required headers
    479449                if( !monitor_decl || !guard_decl || !dtor_guard_decl )
    480                         SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>\n" );
    481 
    482                 // Instrument the body
     450                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
     451
    483452                if( isDtor ) {
    484453                        addDtorStatments( decl, body, mutexArgs );
     
    505474        }
    506475
    507         std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) {
     476        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
    508477                std::list<DeclarationWithType*> mutexArgs;
    509478
    510                 bool once = true;
    511479                for( auto arg : decl->get_functionType()->get_parameters()) {
    512480                        //Find mutex arguments
    513481                        Type* ty = arg->get_type();
    514482                        if( ! ty->get_mutex() ) continue;
    515 
    516                         if(once) {first = true;}
    517                         once = false;
    518483
    519484                        //Append it to the list
  • src/ControlStruct/ForExprMutator.cc

    rb21c77a r97397a26  
    4545                return hoist( forStmt, forStmt->initialization );
    4646        }
    47         Statement *ForExprMutator::postmutate( WhileStmt *whileStmt ) {
    48                 return hoist( whileStmt, whileStmt->initialization );
    49         }
    5047} // namespace ControlStruct
    5148
  • src/ControlStruct/ForExprMutator.h

    rb21c77a r97397a26  
    1818class IfStmt;
    1919class ForStmt;
    20 class WhileStmt;
    2120class Statement;
    2221
     
    2625                Statement *postmutate( IfStmt * );
    2726                Statement *postmutate( ForStmt * );
    28                 Statement *postmutate( WhileStmt * );
    2927        };
    3028} // namespace ControlStruct
  • src/ControlStruct/Mutate.cc

    rb21c77a r97397a26  
    2727#include "SynTree/Visitor.h"       // for acceptAll
    2828
     29using namespace std;
     30
    2931namespace ControlStruct {
    30         void fixLabels( std::list< Declaration * > & translationUnit ) {
     32        void mutate( std::list< Declaration * > translationUnit ) {
     33                // hoist initialization out of for statements
     34                PassVisitor<ForExprMutator> formut;
     35
     36                // normalizes label definitions and generates multi-level exit labels
    3137                PassVisitor<LabelFixer> lfix;
     38
     39                mutateAll( translationUnit, formut );
    3240                acceptAll( translationUnit, lfix );
    33         }
    34 
    35         void hoistControlDecls( std::list< Declaration * > & translationUnit ) {
    36                 PassVisitor<ForExprMutator> formut;
    37                 mutateAll( translationUnit, formut );
    3841        }
    3942} // namespace CodeGen
  • src/ControlStruct/Mutate.h

    rb21c77a r97397a26  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Mutate.h --
     7// Mutate.h -- 
    88//
    99// Author           : Rodolfo G. Esteves
     
    2020class Declaration;
    2121
    22 /// Desugars Cforall control structures
    2322namespace ControlStruct {
    24         /// normalizes label definitions and generates multi-level exit labels
    25         void fixLabels( std::list< Declaration * > & translationUnit );
    26 
    27         /// hoist initialization out of for statements
    28         void hoistControlDecls( std::list< Declaration * > & translationUnit );
     23        /// Desugars Cforall control structures
     24        void mutate( std::list< Declaration* > translationUnit );
    2925} // namespace ControlStruct
    3026
  • src/GenPoly/Lvalue.cc

    rb21c77a r97397a26  
    145145
    146146        namespace {
    147                 // true for intrinsic function calls that return an lvalue in C
     147                // true for intrinsic function calls that return a reference
    148148                bool isIntrinsicReference( Expression * expr ) {
    149                         // known intrinsic-reference prelude functions
    150                         static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    151149                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    152150                                std::string fname = InitTweak::getFunctionName( untyped );
    153                                 return lvalueFunctions.count(fname);
     151                                // known intrinsic-reference prelude functions
     152                                return fname == "*?" || fname == "?[?]";
    154153                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    155154                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    156                                         return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
     155                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     156                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     157                                        Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();
     158                                        return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
    157159                                }
    158160                        }
     
    208210                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    209211
    210                                                 if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     212                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    211213                                                        // needed for definition of prelude functions, etc.
    212214                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    224226                                                        arg = new AddressExpr( arg );
    225227                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    226                                                 } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     228                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    227229                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    228230                                                        PRINT(
  • src/Parser/DeclarationNode.cc

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  7 12:08:55 2018
    13 // Update Count     : 1079
     12// Last Modified On : Tue May 22 08:39:29 2018
     13// Update Count     : 1074
    1414//
    1515
     
    173173}
    174174
    175 DeclarationNode * DeclarationNode::newFunction( const string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
     175DeclarationNode * DeclarationNode::newFunction( string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
    176176        DeclarationNode * newnode = new DeclarationNode;
    177177        newnode->name = name;
     
    244244} // DeclarationNode::newForall
    245245
    246 DeclarationNode * DeclarationNode::newFromTypedef( const string * name ) {
     246DeclarationNode * DeclarationNode::newFromTypedef( string * name ) {
    247247        DeclarationNode * newnode = new DeclarationNode;
    248248        newnode->type = new TypeData( TypeData::SymbolicInst );
     
    267267} // DeclarationNode::newAggregate
    268268
    269 DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body ) {
     269DeclarationNode * DeclarationNode::newEnum( string * name, DeclarationNode * constants, bool body ) {
    270270        assert( name );
    271271        DeclarationNode * newnode = new DeclarationNode;
     
    277277} // DeclarationNode::newEnum
    278278
    279 DeclarationNode * DeclarationNode::newEnumConstant( const string * name, ExpressionNode * constant ) {
     279DeclarationNode * DeclarationNode::newEnumConstant( string * name, ExpressionNode * constant ) {
    280280        DeclarationNode * newnode = new DeclarationNode;
    281281        newnode->name = name;
     
    284284} // DeclarationNode::newEnumConstant
    285285
    286 DeclarationNode * DeclarationNode::newName( const string * name ) {
     286DeclarationNode * DeclarationNode::newName( string * name ) {
    287287        DeclarationNode * newnode = new DeclarationNode;
    288288        newnode->name = name;
     
    290290} // DeclarationNode::newName
    291291
    292 DeclarationNode * DeclarationNode::newFromTypeGen( const string * name, ExpressionNode * params ) {
     292DeclarationNode * DeclarationNode::newFromTypeGen( string * name, ExpressionNode * params ) {
    293293        DeclarationNode * newnode = new DeclarationNode;
    294294        newnode->type = new TypeData( TypeData::SymbolicInst );
     
    299299} // DeclarationNode::newFromTypeGen
    300300
    301 DeclarationNode * DeclarationNode::newTypeParam( TypeClass tc, const string * name ) {
     301DeclarationNode * DeclarationNode::newTypeParam( TypeClass tc, string * name ) {
    302302        DeclarationNode * newnode = new DeclarationNode;
    303303        newnode->type = nullptr;
     
    330330} // DeclarationNode::newTraitUse
    331331
    332 DeclarationNode * DeclarationNode::newTypeDecl( const string * name, DeclarationNode * typeParams ) {
     332DeclarationNode * DeclarationNode::newTypeDecl( string * name, DeclarationNode * typeParams ) {
    333333        DeclarationNode * newnode = new DeclarationNode;
    334334        newnode->name = name;
     
    405405} // DeclarationNode::newBuiltinType
    406406
    407 DeclarationNode * DeclarationNode::newAttr( const string * name, ExpressionNode * expr ) {
     407DeclarationNode * DeclarationNode::newAttr( string * name, ExpressionNode * expr ) {
    408408        DeclarationNode * newnode = new DeclarationNode;
    409409        newnode->type = nullptr;
     
    414414}
    415415
    416 DeclarationNode * DeclarationNode::newAttr( const string * name, DeclarationNode * type ) {
     416DeclarationNode * DeclarationNode::newAttr( string * name, DeclarationNode * type ) {
    417417        DeclarationNode * newnode = new DeclarationNode;
    418418        newnode->type = nullptr;
     
    423423}
    424424
    425 DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
     425DeclarationNode * DeclarationNode::newAttribute( string * name, ExpressionNode * expr ) {
    426426        DeclarationNode * newnode = new DeclarationNode;
    427427        newnode->type = nullptr;
     
    544544                                        type->aggregate.params->appendList( q->type->forall ); // augment forall qualifier
    545545                                } else {                                                                // not polymorphic
    546                                         type->aggregate.params = q->type->forall; // set forall qualifier
     546                                        type->aggregate.params = q->type->forall; // make polymorphic type
     547                                        // change implicit typedef from TYPEDEFname to TYPEGENname
     548                                        typedefTable.changeKind( *type->aggregate.name, TYPEGENname );
    547549                                } // if
    548550                        } else {                                                                        // not polymorphic
     
    10631065                        SemanticError( this, "invalid function specifier for " );
    10641066                } // if
    1065                 bool isDelete = initializer && initializer->get_isDelete();
    1066                 Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
    1067                 if ( isDelete ) {
    1068                         DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );
    1069                         dwt->isDeleted = true;
    1070                 }
    1071                 return decl;
     1067                return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
    10721068        } // if
    10731069
  • src/Parser/ExpressionNode.cc

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  4 21:24:45 2018
    13 // Update Count     : 802
     12// Last Modified On : Thu Mar 22 11:57:39 2018
     13// Update Count     : 801
    1414//
    1515
     
    314314
    315315Expression * build_constantStr( string & str ) {
    316         assert( str.length() > 0 );
    317316        string units;                                                                           // units
    318317        sepString( str, units, '"' );                                           // separate constant from units
  • src/Parser/InitializerNode.cc

    rb21c77a r97397a26  
    2727
    2828InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
    29                 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
     29                : expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ) {
    3030        if ( aggrp )
    3131                kids = dynamic_cast< InitializerNode * >( get_next() );
     
    3636
    3737InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des )
    38                 : expr( nullptr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
     38                : expr( nullptr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ) {
    3939        if ( init )
    4040                set_last( init );
     
    4646                set_next( nullptr );
    4747} // InitializerNode::InitializerNode
    48 
    49 InitializerNode::InitializerNode( bool isDelete ) : expr( nullptr ), aggregate( false ), designator( nullptr ), kids( nullptr ), maybeConstructed( false ), isDelete( isDelete ) {}
    5048
    5149InitializerNode::~InitializerNode() {
     
    8684
    8785Initializer * InitializerNode::build() const {
    88         assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
    8986        if ( aggregate ) {
    9087                // steal designators from children
  • src/Parser/ParseNode.h

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 16:17:18 2018
    13 // Update Count     : 843
     12// Last Modified On : Mon Apr 30 09:19:17 2018
     13// Update Count     : 831
    1414//
    1515
     
    7777
    7878        ParseNode * next = nullptr;
    79         const std::string * name = nullptr;
     79        std::string * name = nullptr;
    8080        CodeLocation location = yylloc;
    8181}; // ParseNode
     
    8787        InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode * des = nullptr );
    8888        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    89         InitializerNode( bool isDelete );
    9089        ~InitializerNode();
    9190        virtual InitializerNode * clone() const { assert( false ); return nullptr; }
     
    9897        InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
    9998        bool get_maybeConstructed() const { return maybeConstructed; }
    100 
    101         bool get_isDelete() const { return isDelete; }
    10299
    103100        InitializerNode * next_init() const { return kids; }
     
    113110        InitializerNode * kids;
    114111        bool maybeConstructed;
    115         bool isDelete;
    116112}; // InitializerNode
    117113
     
    171167};
    172168
    173 Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
    174 Expression * build_constantFloat( std::string & str );
    175 Expression * build_constantChar( std::string & str );
    176 Expression * build_constantStr( std::string & str );
     169Expression * build_constantInteger( std::string &str );
     170Expression * build_constantFloat( std::string &str );
     171Expression * build_constantChar( std::string &str );
     172Expression * build_constantStr( std::string &str );
    177173Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
    178174Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
     
    230226        static DeclarationNode * newBuiltinType( BuiltinType );
    231227        static DeclarationNode * newForall( DeclarationNode * );
    232         static DeclarationNode * newFromTypedef( const std::string * );
    233         static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
     228        static DeclarationNode * newFromTypedef( std::string * );
     229        static DeclarationNode * newFunction( std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    234230        static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    235         static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body );
    236         static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
    237         static DeclarationNode * newName( const std::string * );
    238         static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
    239         static DeclarationNode * newTypeParam( TypeClass, const std::string * );
     231        static DeclarationNode * newEnum( std::string * name, DeclarationNode * constants, bool body );
     232        static DeclarationNode * newEnumConstant( std::string * name, ExpressionNode * constant );
     233        static DeclarationNode * newName( std::string * );
     234        static DeclarationNode * newFromTypeGen( std::string *, ExpressionNode * params );
     235        static DeclarationNode * newTypeParam( TypeClass, std::string * );
    240236        static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
    241237        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    242         static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );
     238        static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
    243239        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    244240        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
     
    247243        static DeclarationNode * newTuple( DeclarationNode * members );
    248244        static DeclarationNode * newTypeof( ExpressionNode * expr );
    249         static DeclarationNode * newAttr( const std::string *, ExpressionNode * expr ); // @ attributes
    250         static DeclarationNode * newAttr( const std::string *, DeclarationNode * type ); // @ attributes
    251         static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
     245        static DeclarationNode * newAttr( std::string *, ExpressionNode * expr ); // @ attributes
     246        static DeclarationNode * newAttr( std::string *, DeclarationNode * type ); // @ attributes
     247        static DeclarationNode * newAttribute( std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    252248        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
    253249        static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
     
    403399};
    404400
    405 Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init );
    406401Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
    407402Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
    408403Statement * build_case( ExpressionNode * ctl );
    409404Statement * build_default();
    410 Statement * build_while( IfCtl * ctl, StatementNode * stmt );
    411 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt );
     405Statement * build_while( ExpressionNode * ctl, StatementNode * stmt, bool kind = false );
    412406Statement * build_for( ForCtl * forctl, StatementNode * stmt );
    413407Statement * build_branch( BranchStmt::Type kind );
  • src/Parser/StatementNode.cc

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 08:58:34 2018
    13 // Update Count     : 362
     12// Last Modified On : Mon Apr 30 09:21:16 2018
     13// Update Count     : 354
    1414//
    1515
     
    6969        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
    7070        return this;
    71 } // StatementNode::append_last_case
     71}
    7272
    7373Statement * build_expr( ExpressionNode * ctl ) {
    7474        Expression * e = maybeMoveBuild< Expression >( ctl );
    7575
    76         if ( e ) return new ExprStmt( e );
    77         else return new NullStmt();
    78 } // build_expr
    79 
    80 Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init ) {
     76        if ( e )
     77                return new ExprStmt( e );
     78        else
     79                return new NullStmt();
     80}
     81
     82Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt ) {
     83        Statement * thenb, * elseb = 0;
     84        std::list< Statement * > branches;
     85        buildMoveList< Statement, StatementNode >( then_stmt, branches );
     86        assert( branches.size() == 1 );
     87        thenb = branches.front();
     88
     89        if ( else_stmt ) {
     90                std::list< Statement * > branches;
     91                buildMoveList< Statement, StatementNode >( else_stmt, branches );
     92                assert( branches.size() == 1 );
     93                elseb = branches.front();
     94        } // if
     95
     96        std::list< Statement * > init;
    8197        if ( ctl->init != 0 ) {
    8298                buildMoveList( ctl->init, init );
     
    86102        if ( ctl->condition ) {
    87103                // compare the provided condition against 0
    88                 cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
     104                cond =  notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
    89105        } else {
    90106                for ( Statement * stmt : init ) {
     
    97113        }
    98114        delete ctl;
    99         return cond;
    100 } // build_if_control
    101 
    102 Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt ) {
    103         Statement * thenb, * elseb = nullptr;
    104         std::list< Statement * > branches;
    105         buildMoveList< Statement, StatementNode >( then_stmt, branches );
    106         assert( branches.size() == 1 );
    107         thenb = branches.front();
    108 
    109         if ( else_stmt ) {
    110                 std::list< Statement * > branches;
    111                 buildMoveList< Statement, StatementNode >( else_stmt, branches );
    112                 assert( branches.size() == 1 );
    113                 elseb = branches.front();
    114         } // if
    115 
    116         std::list< Statement * > init;
    117         Expression * cond = build_if_control( ctl, init );
    118115        return new IfStmt( cond, thenb, elseb, init );
    119 } // build_if
     116}
    120117
    121118Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
     
    133130        // branches.size() == 0 for switch (...) {}, i.e., no declaration or statements
    134131        return new SwitchStmt( maybeMoveBuild< Expression >(ctl), branches );
    135 } // build_switch
    136 
     132}
    137133Statement * build_case( ExpressionNode * ctl ) {
    138134        std::list< Statement * > branches;
    139135        return new CaseStmt( maybeMoveBuild< Expression >(ctl), branches );
    140 } // build_case
    141 
     136}
    142137Statement * build_default() {
    143138        std::list< Statement * > branches;
    144139        return new CaseStmt( nullptr, branches, true );
    145 } // build_default
    146 
    147 Statement * build_while( IfCtl * ctl, StatementNode * stmt ) {
     140}
     141
     142Statement * build_while( ExpressionNode * ctl, StatementNode * stmt, bool kind ) {
    148143        std::list< Statement * > branches;
    149144        buildMoveList< Statement, StatementNode >( stmt, branches );
    150145        assert( branches.size() == 1 );
    151 
    152         std::list< Statement * > init;
    153         Expression * cond = build_if_control( ctl, init );
    154         return new WhileStmt( cond, branches.front(), init, false );
    155 } // build_while
    156 
    157 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt ) {
    158         std::list< Statement * > branches;
    159         buildMoveList< Statement, StatementNode >( stmt, branches );
    160         assert( branches.size() == 1 );
    161 
    162         std::list< Statement * > init;
    163         return new WhileStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), init, true );
    164 } // build_do_while
     146        return new WhileStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind );
     147}
    165148
    166149Statement * build_for( ForCtl * forctl, StatementNode * stmt ) {
     
    184167        delete forctl;
    185168        return new ForStmt( init, cond, incr, branches.front() );
    186 } // build_for
     169}
    187170
    188171Statement * build_branch( BranchStmt::Type kind ) {
    189172        Statement * ret = new BranchStmt( "", kind );
    190173        return ret;
    191 } // build_branch
    192 
     174}
    193175Statement * build_branch( std::string * identifier, BranchStmt::Type kind ) {
    194176        Statement * ret = new BranchStmt( * identifier, kind );
    195177        delete identifier;                                                                      // allocated by lexer
    196178        return ret;
    197 } // build_branch
    198 
     179}
    199180Statement * build_computedgoto( ExpressionNode * ctl ) {
    200181        return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
    201 } // build_computedgoto
     182}
    202183
    203184Statement * build_return( ExpressionNode * ctl ) {
     
    205186        buildMoveList( ctl, exps );
    206187        return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
    207 } // build_return
     188}
    208189
    209190Statement * build_throw( ExpressionNode * ctl ) {
     
    212193        assertf( exps.size() < 2, "This means we are leaking memory");
    213194        return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
    214 } // build_throw
     195}
    215196
    216197Statement * build_resume( ExpressionNode * ctl ) {
     
    219200        assertf( exps.size() < 2, "This means we are leaking memory");
    220201        return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
    221 } // build_resume
     202}
    222203
    223204Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     
    225206        (void)target;
    226207        assertf( false, "resume at (non-local throw) is not yet supported," );
    227 } // build_resume_at
     208}
    228209
    229210Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt ) {
     
    233214        FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) );
    234215        return new TryStmt( tryBlock, branches, finallyBlock );
    235 } // build_try
    236 
     216}
    237217Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    238218        std::list< Statement * > branches;
     
    240220        assert( branches.size() == 1 );
    241221        return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
    242 } // build_catch
    243 
     222}
    244223Statement * build_finally( StatementNode * stmt ) {
    245224        std::list< Statement * > branches;
     
    247226        assert( branches.size() == 1 );
    248227        return new FinallyStmt( dynamic_cast< CompoundStmt * >( branches.front() ) );
    249 } // build_finally
     228}
    250229
    251230WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
     
    268247
    269248        return node;
    270 } // build_waitfor
     249}
    271250
    272251WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
     
    287266
    288267        return node;
    289 } // build_waitfor
     268}
    290269
    291270WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
     
    296275                node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    297276                node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    298         } else {
     277        }
     278        else {
    299279                node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
    300280                node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    301         } // if
     281        }
    302282
    303283        return node;
    304 } // build_waitfor_timeout
     284}
    305285
    306286WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_stmt, ExpressionNode * else_when ) {
     
    315295
    316296        return node;
    317 } // build_waitfor_timeout
     297}
    318298
    319299WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     
    322302        Statement * s = maybeMoveBuild<Statement>( stmt );
    323303        return new WithStmt( e, s );
    324 } // build_with
     304}
    325305
    326306Statement * build_compound( StatementNode * first ) {
     
    328308        buildMoveList( first, cs->get_kids() );
    329309        return cs;
    330 } // build_compound
     310}
    331311
    332312Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     
    338318        buildMoveList( clobber, clob );
    339319        return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    340 } // build_asm
     320}
    341321
    342322Statement * build_directive( string * directive ) {
    343323        return new DirectiveStmt( *directive );
    344 } // build_directive
     324}
    345325
    346326// Local Variables: //
  • src/Parser/TypeData.cc

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 17:40:33 2018
    13 // Update Count     : 604
     12// Last Modified On : Thu Apr 26 13:46:07 2018
     13// Update Count     : 603
    1414//
    1515
     
    6565          case Aggregate:
    6666                // aggregate = new Aggregate_t;
    67                 aggregate.kind = DeclarationNode::NoAggregate;
    6867                aggregate.name = nullptr;
    6968                aggregate.params = nullptr;
     
    7170                aggregate.fields = nullptr;
    7271                aggregate.body = false;
    73                 aggregate.tagged = false;
    74                 aggregate.parent = nullptr;
    7572                break;
    7673          case AggregateInst:
     
    201198                break;
    202199          case Aggregate:
    203                 newtype->aggregate.kind = aggregate.kind;
    204200                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
    205201                newtype->aggregate.params = maybeClone( aggregate.params );
    206202                newtype->aggregate.actuals = maybeClone( aggregate.actuals );
    207203                newtype->aggregate.fields = maybeClone( aggregate.fields );
     204                newtype->aggregate.kind = aggregate.kind;
    208205                newtype->aggregate.body = aggregate.body;
    209206                newtype->aggregate.tagged = aggregate.tagged;
     
    578575
    579576          case DeclarationNode::Int128:
    580                 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
     577                ret = td->signedness == 1 ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
    581578                if ( td->length != DeclarationNode::NoLength ) {
    582579                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     
    602599                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    603600                } // if
    604                 if ( td->basictype != DeclarationNode::Double && td->length == DeclarationNode::Long ) {
     601                if ( td->basictype == DeclarationNode::Float && td->length == DeclarationNode::Long ) {
    605602                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    606603                } // if
     
    608605                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
    609606                } // if
    610 
    611                 if ( td->basictype == DeclarationNode::Float80 || td->basictype == DeclarationNode::Float128 ) {
    612                         // if ( td->complextype != DeclarationNode::NoComplexType ) {
    613                         //      genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
    614                         // }
    615                         if ( td->basictype == DeclarationNode::Float80 ) ret = BasicType::Float80;
    616                         else ret = BasicType::Float128;
    617                         break;
    618                 }
    619607
    620608                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
  • src/Parser/TypedefTable.cc

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 15:20:13 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 22 06:14:39 2018
    13 // Update Count     : 206
     12// Last Modified On : Tue May 22 08:40:01 2018
     13// Update Count     : 121
    1414//
    1515
     
    1717#include "TypedefTable.h"
    1818#include <cassert>                                                                              // for assert
    19 #include <iostream>
    2019
    2120#if 0
    22 #define debugPrint( code ) code
     21#include <iostream>
     22#define debugPrint( x ) cerr << x
    2323#else
    24 #define debugPrint( code )
     24#define debugPrint( x )
    2525#endif
    2626
    2727using namespace std;                                                                    // string, iostream
    2828
    29 debugPrint(
    30 static const char *kindName( int kind ) {
    31         switch ( kind ) {
    32           case IDENTIFIER: return "identifier";
    33           case TYPEDEFname: return "typedef";
    34           case TYPEGENname: return "typegen";
    35           default:
    36                 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
    37                 abort();
    38         } // switch
    39 } // kindName
    40 )
    41 
    4229TypedefTable::~TypedefTable() {
    4330        if ( ! SemanticErrorThrow && kindTable.currentScope() != 0 ) {
    44                 cerr << "Error: cfa-cpp internal error, scope failure " << kindTable.currentScope() << endl;
    45                 abort();
     31                // std::cerr << "scope failure " << kindTable.currentScope() << endl;
    4632        } // if
    4733} // TypedefTable::~TypedefTable
     
    5844} // TypedefTable::isKind
    5945
     46void TypedefTable::changeKind( const string & identifier, int kind ) {
     47        KindTable::iterator posn = kindTable.find( identifier );
     48        if ( posn != kindTable.end() ) posn->second = kind;     // exists => update
     49} // TypedefTable::changeKind
     50
    6051// SKULLDUGGERY: Generate a typedef for the aggregate name so the aggregate does not have to be qualified by
    6152// "struct". Only generate the typedef, if the name is not in use. The typedef is implicitly (silently) removed if the
    6253// name is explicitly used.
    63 void TypedefTable::makeTypedef( const string & name, int kind ) {
    64 //    Check for existence is necessary to handle:
    65 //        struct Fred {};
    66 //        void Fred();
    67 //        void fred() {
    68 //           struct Fred act; // do not add as type in this scope
    69 //           Fred();
    70 //        }
     54void TypedefTable::makeTypedef( const string & name ) {
    7155        if ( ! typedefTable.exists( name ) ) {
    72                 typedefTable.addToEnclosingScope( name, kind, "MTD" );
     56                typedefTable.addToEnclosingScope( name, TYPEDEFname );
    7357        } // if
    7458} // TypedefTable::makeTypedef
    7559
    76 void TypedefTable::addToScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    77         auto scope = kindTable.currentScope();
    78         debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    79         auto ret = kindTable.insertAt( scope, identifier, kind );
    80         //if ( ! ret.second ) ret.first->second = kind;         // exists => update
    81         assert( ret.first->second == kind );                            // exists
    82 } // TypedefTable::addToScope
    83 
    84 void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    85         assert( kindTable.currentScope() >= 1 + level );
    86         auto scope = kindTable.currentScope() - 1 - level;
    87         debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << " level " << level << endl );
     60void TypedefTable::addToEnclosingScope( const std::string & identifier, int kind ) {
     61        assert( kindTable.currentScope() >= 1 );
     62        auto scope = kindTable.currentScope() - 1;
     63        debugPrint( "Adding " << identifier << " as kind " << kind << " scope " << scope << endl );
    8864        auto ret = kindTable.insertAt( scope, identifier, kind );
    8965        if ( ! ret.second ) ret.first->second = kind;           // exists => update
     
    9268void TypedefTable::enterScope() {
    9369        kindTable.beginScope();
    94         debugPrint( cerr << "Entering scope " << kindTable.currentScope() << endl; print() );
     70        debugPrint( "Entering scope " << kindTable.currentScope() << endl );
    9571} // TypedefTable::enterScope
    9672
    9773void TypedefTable::leaveScope() {
    98         debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl; print() );
     74        debugPrint( "Leaving scope " << kindTable.currentScope() << endl );
    9975        kindTable.endScope();
    10076} // TypedefTable::leaveScope
    10177
    102 void TypedefTable::print( void ) const {
    103         KindTable::size_type scope = kindTable.currentScope();
    104         debugPrint( cerr << "[" << scope << "]" );
    105         for ( KindTable::const_iterator i = kindTable.begin(); i != kindTable.end(); i++ ) {
    106                 while ( i.get_level() != scope ) {
    107                         --scope;
    108                         debugPrint( cerr << endl << "[" << scope << "]" );
    109                 } // while
    110                 debugPrint( cerr << " " << (*i).first << ":" << kindName( (*i).second ) );
    111         } // for
    112         while ( scope > 0 ) {
    113                 --scope;
    114                 debugPrint( cerr << endl << "[" << scope << "]" );
    115         } // while
    116         debugPrint( cerr << endl );
    117 } // TypedefTable::print
     78// void TypedefTable::print( void ) const {
     79//      for ( KindTable::const_iterator i = table.begin(); i != table.end(); i++) {
     80//              debugPrint( (*i ).first << ": " );
     81//              list< Entry > declList = (*i).second;
     82//              for ( list< Entry >::const_iterator j = declList.begin(); j != declList.end(); j++ ) {
     83//                      debugPrint( "(" << (*j).scope << " " << (*j).kind << ") " );
     84//              }
     85//              debugPrint( endl );
     86//      } // for
     87// }
    11888
    11989// Local Variables: //
  • src/Parser/TypedefTable.h

    rb21c77a r97397a26  
    1010// Created On       : Sat May 16 15:24:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 22 05:29:58 2018
    13 // Update Count     : 86
     12// Last Modified On : Tue May 22 08:39:29 2018
     13// Update Count     : 77
    1414//
    1515
     
    2525        typedef ScopedMap< std::string, int > KindTable;
    2626        KindTable kindTable;   
    27         unsigned int level = 0;
    2827  public:
    2928        ~TypedefTable();
     
    3130        bool exists( const std::string & identifier );
    3231        int isKind( const std::string & identifier ) const;
    33         void makeTypedef( const std::string & name, int kind = TYPEDEFname );
    34         void addToScope( const std::string & identifier, int kind, const char * );
    35         void addToEnclosingScope( const std::string & identifier, int kind, const char * );
     32        void changeKind( const std::string & identifier, int kind );
     33        void makeTypedef( const std::string & name );
     34        void addToEnclosingScope( const std::string & identifier, int kind );
    3635
    3736        void enterScope();
    3837        void leaveScope();
    39 
    40         void up() { level += 1; }
    41         void down() { level -= 1; }
    42 
    43         void print( void ) const;
    4438}; // TypedefTable
    4539
  • src/Parser/lex.ll

    rb21c77a r97397a26  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Wed Jun 20 09:08:28 2018
    13  * Update Count     : 682
     12 * Last Modified On : Thu May  3 13:42:40 2018
     13 * Update Count     : 676
    1414 */
    1515
     
    2525//**************************** Includes and Defines ****************************
    2626
    27 // trigger before each matching rule's action
    28 #define YY_USER_ACTION \
    29         yylloc.first_line = yylineno; \
    30         yylloc.first_column = column; \
    31         column += yyleng; \
    32         yylloc.last_column = column; \
    33         yylloc.last_line = yylineno; \
    34         yylloc.filename = yyfilename ? yyfilename : "";
    3527unsigned int column = 0;                                                                // position of the end of the last token parsed
     28#define YY_USER_ACTION yylloc.first_line = yylineno; yylloc.first_column = column; column += yyleng; yylloc.last_column = column; yylloc.last_line = yylineno; yylloc.filename = yyfilename ? yyfilename : "";                          // trigger before each matching rule's action
    3629
    3730#include <string>
     
    5649#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL( x ) // numeric constant
    5750#define KEYWORD_RETURN(x)       RETURN_CHAR( x )                        // keyword
    58 #define QKEYWORD_RETURN(x)      RETURN_VAL(x);                          // quasi-keyword
     51#define QKEYWORD_RETURN(x)      typedefTable.isKind( yytext ); RETURN_VAL(x); // quasi-keyword
    5952#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    6053#define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
     
    239232finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    240233float                   { KEYWORD_RETURN(FLOAT); }
    241 _Float32                { KEYWORD_RETURN(FLOAT); }                              // GCC
    242 _Float32x               { KEYWORD_RETURN(FLOAT); }                              // GCC
    243 _Float64                { KEYWORD_RETURN(DOUBLE); }                             // GCC
    244 _Float64x               { KEYWORD_RETURN(DOUBLE); }                             // GCC
    245234__float80               { KEYWORD_RETURN(FLOAT80); }                    // GCC
    246235float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
    247 _Float128               { KEYWORD_RETURN(FLOAT128); }                   // GCC
    248 _Float128x              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    249236__float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    250237float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
     
    459446
    460447%%
    461 
    462448// ----end of lexer----
    463449
    464450void yyerror( const char * errmsg ) {
    465         SemanticErrorThrow = true;
    466451        cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    467452                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
  • src/Parser/parser.yy

    rb21c77a r97397a26  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 22 13:59:11 2018
    13 // Update Count     : 3586
     12// Last Modified On : Thu May 24 18:11:59 2018
     13// Update Count     : 3369
    1414//
    1515
     
    136136} // build_postfix_name
    137137
    138 bool forall = false, xxx = false, yyy = false;                  // aggregate have one or more forall qualifiers ?
     138bool forall = false, xxx = false;                                               // aggregate have one or more forall qualifiers ?
    139139
    140140// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
     
    175175        bool flag;
    176176        CatchStmt::Kind catch_kind;
    177         GenericExpr * genexpr;
    178177}
    179178
     
    260259%type<flag> asm_volatile_opt
    261260%type<en> handler_predicate_opt
    262 %type<genexpr> generic_association generic_assoc_list
    263261
    264262// statements
    265263%type<sn> statement                                             labeled_statement                       compound_statement
    266264%type<sn> statement_decl                                statement_decl_list                     statement_list_nodecl
    267 %type<sn> selection_statement                   if_statement
     265%type<sn> selection_statement
    268266%type<sn> switch_clause_list_opt                switch_clause_list
    269267%type<en> case_value
     
    304302%type<en> enumerator_value_opt
    305303
    306 %type<decl> external_definition external_definition_list external_definition_list_opt
    307 
    308 %type<decl> exception_declaration
     304%type<decl> exception_declaration external_definition external_definition_list external_definition_list_opt
    309305
    310306%type<decl> field_declaration field_declaration_list_opt field_declarator_opt field_declaring_list
     
    328324%type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr
    329325
    330 %type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt
     326%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_type_list_opt
    331327
    332328%type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier
     
    334330%type<decl> c_declaration static_assert
    335331%type<decl> KR_function_declarator KR_function_no_ptr KR_function_ptr KR_function_array
    336 %type<decl> KR_parameter_list KR_parameter_list_opt
     332%type<decl> KR_declaration_list KR_declaration_list_opt
    337333
    338334%type<decl> parameter_declaration parameter_list parameter_type_list_opt
     
    406402//************************* Namespace Management ********************************
    407403
    408 // The C grammar is not context free because it relies on the distinct terminal symbols "identifier" and "TYPEDEFname",
    409 // which are lexically identical.
    410 //
    411 //   typedef int foo; // identifier foo must now be scanned as TYPEDEFname
    412 //   foo f;           // to allow it to appear in this context
    413 //
    414 // While it may be possible to write a purely context-free grammar, such a grammar would obscure the relationship
    415 // between syntactic and semantic constructs.  Cforall compounds this problem by introducing type names local to the
    416 // scope of a declaration (for instance, those introduced through "forall" qualifiers), and by introducing "type
    417 // generators" -- parameterized types.  This latter type name creates a third class of identifiers, "TYPEGENname", which
    418 // must be distinguished by the lexical scanner.
    419 //
    420 // Since the scanner cannot distinguish among the different classes of identifiers without some context information,
    421 // there is a type table (typedefTable), which holds type names and identifiers that override type names, for each named
    422 // scope. During parsing, semantic actions update the type table by adding new identifiers in the current scope. For
    423 // each context that introduces a name scope, a new level is created in the type table and that level is popped on
    424 // exiting the scope.  Since type names can be local to a particular declaration, each declaration is itself a scope.
    425 // This requires distinguishing between type names that are local to the current declaration scope and those that
    426 // persist past the end of the declaration (i.e., names defined in "typedef" or "otype" declarations).
    427 //
    428 // The non-terminals "push" and "pop" denote the opening and closing of named scopes. Every push has a matching pop in
    429 // the production rule. There are multiple lists of declarations, where each declaration is a named scope, so pop/push
    430 // around the list separator.
    431 //
    432 //  int f( forall(T) T (*f1) T , forall( S ) S (*f2)( S ) );
    433 //      push               pop   push                   pop
     404// The grammar in the ANSI C standard is not strictly context-free, since it relies upon the distinct terminal symbols
     405// "identifier", "TYPEDEFname", and "TYPEGENname" that are lexically identical.  While it is possible to write a purely
     406// context-free grammar, such a grammar would obscure the relationship between syntactic and semantic constructs.
     407// Hence, this grammar uses the ANSI style.
     408//
     409// Cforall compounds this problem by introducing type names local to the scope of a declaration (for instance, those
     410// introduced through "forall" qualifiers), and by introducing "type generators" -- parameterized types.  This latter
     411// type name creates a third class of identifiers that must be distinguished by the scanner.
     412//
     413// Since the scanner cannot distinguish among the different classes of identifiers without some context information, it
     414// accesses a data structure (TypedefTable) to allow classification of an identifier that it has just read.  Semantic
     415// actions during the parser update this data structure when the class of identifiers change.
     416//
     417// Because the Cforall language is block-scoped, an identifier can change its class in a local scope; it must revert to
     418// its original class at the end of the block.  Since type names can be local to a particular declaration, each
     419// declaration is itself a scope.  This requires distinguishing between type names that are local to the current
     420// declaration scope and those that persist past the end of the declaration (i.e., names defined in "typedef" or "otype"
     421// declarations).
     422//
     423// The non-terminals "push" and "pop" denote the opening and closing of scopes.  Every push must have a matching pop,
     424// although it is regrettable the matching pairs do not always occur within the same rule.  These non-terminals may
     425// appear in more contexts than strictly necessary from a semantic point of view.
    434426
    435427push:
     
    505497                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    506498        | type_name '.' no_attr_identifier                                      // CFA, nested type
    507                 // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    508                 { $$ = nullptr; }
     499                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    509500        | type_name '.' '[' field_list ']'                                      // CFA, nested type / tuple field selector
    510                 // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    511                 { $$ = nullptr; }
     501                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    512502        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    513                 {
    514                         // add the missing control expression to the GenericExpr and return it
    515                         $5->control = maybeMoveBuild<Expression>( $3 );
    516                         $$ = new ExpressionNode( $5 );
    517                 }
     503                { SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; }
    518504        ;
    519505
    520506generic_assoc_list:                                                                             // C11
    521         generic_association
     507        | generic_association
    522508        | generic_assoc_list ',' generic_association
    523                 {
    524                         // steal the association node from the singleton and delete the wrapper
    525                         $1->associations.splice($1->associations.end(), $3->associations);
    526                         delete $3;
    527                         $$ = $1;
    528                 }
    529509        ;
    530510
    531511generic_association:                                                                    // C11
    532512        type_no_function ':' assignment_expression
    533                 {
    534                         // create a GenericExpr wrapper with one association pair
    535                         $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>($3) } } );
    536                 }
    537513        | DEFAULT ':' assignment_expression
    538                 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>($3) } } ); }
    539514        ;
    540515
     
    648623                // semantics checks, e.g., ++3, 3--, *3, &&3
    649624        | constant
     625                { $$ = $1; }
    650626        | string_literal
    651627                { $$ = new ExpressionNode( $1 ); }
     
    859835//      '[' ']'
    860836//              { $$ = new ExpressionNode( build_tuple() ); }
    861 //      | '[' push assignment_expression pop ']'
     837//      '[' push assignment_expression pop ']'
    862838//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    863         '[' ',' tuple_expression_list ']'
    864                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
    865         | '[' push assignment_expression pop ',' tuple_expression_list ']'
    866                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)$3->set_last( $6 ) ) ); }
     839        '[' push ',' tuple_expression_list pop ']'
     840                { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $4 ) ) ); }
     841        | '[' push assignment_expression ',' tuple_expression_list pop ']'
     842                { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)$3->set_last( $5 ) ) ); }
    867843        ;
    868844
     
    916892        '{' '}'
    917893                { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
    918         | '{' push
     894        | '{'
     895                // Two scopes are necessary because the block itself has a scope, but every declaration within the block also
     896                // requires its own scope.
     897          push push
    919898          local_label_declaration_opt                                           // GCC, local labels
    920899          statement_decl_list                                                           // C99, intermix declarations and statements
    921900          pop '}'
    922                 { $$ = new StatementNode( build_compound( $4 ) ); }
     901                { $$ = new StatementNode( build_compound( $5 ) ); }
    923902        ;
    924903
    925904statement_decl_list:                                                                    // C99
    926905        statement_decl
    927         | statement_decl_list statement_decl
    928                 { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
     906        | statement_decl_list push statement_decl
     907                { if ( $1 != 0 ) { $1->set_last( $3 ); $$ = $1; } }
    929908        ;
    930909
     
    944923                        $$ = new StatementNode( $2 );
    945924                }
    946         | statement
     925        | statement pop
    947926        ;
    948927
     
    959938
    960939selection_statement:
    961                         // pop causes a S/R conflict without separating the IF statement into a non-terminal even after resolving
    962                         // the inherent S/R conflict with THEN/ELSE.
    963         push if_statement pop
    964                 { $$ = $2; }
     940        IF '(' push if_control_expression ')' statement         %prec THEN
     941                // explicitly deal with the shift/reduce conflict on if/else
     942                { $$ = new StatementNode( build_if( $4, $6, nullptr ) ); }
     943        | IF '(' push if_control_expression ')' statement ELSE statement
     944                { $$ = new StatementNode( build_if( $4, $6, $8 ) ); }
    965945        | SWITCH '(' comma_expression ')' case_clause
    966946                { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
    967         | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
     947        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
    968948                {
    969949                        StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
     
    977957        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    978958                { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
    979         | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
     959        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
    980960                {
    981961                        StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
     
    984964        ;
    985965
    986 if_statement:
    987         IF '(' if_control_expression ')' statement                      %prec THEN
    988                 // explicitly deal with the shift/reduce conflict on if/else
    989                 { $$ = new StatementNode( build_if( $3, $5, nullptr ) ); }
    990         | IF '(' if_control_expression ')' statement ELSE statement
    991                 { $$ = new StatementNode( build_if( $3, $5, $7 ) ); }
    992         ;
    993 
    994966if_control_expression:
    995         comma_expression
     967        comma_expression pop
    996968                { $$ = new IfCtl( nullptr, $1 ); }
    997         | c_declaration                                                                         // no semi-colon
     969        | c_declaration pop                                                                     // no semi-colon
    998970                { $$ = new IfCtl( $1, nullptr ); }
    999         | cfa_declaration                                                                       // no semi-colon
     971        | cfa_declaration pop                                                           // no semi-colon
    1000972                { $$ = new IfCtl( $1, nullptr ); }
    1001973        | declaration comma_expression                                          // semi-colon separated
     
    10541026
    10551027iteration_statement:
    1056         WHILE '(' push if_control_expression ')' statement pop
    1057                 { $$ = new StatementNode( build_while( $4, $6 ) ); }
     1028        WHILE '(' comma_expression ')' statement
     1029                { $$ = new StatementNode( build_while( $3, $5 ) ); }
    10581030        | DO statement WHILE '(' comma_expression ')' ';'
    1059                 { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
    1060         | FOR '(' push for_control_expression ')' statement pop
     1031                { $$ = new StatementNode( build_while( $5, $2, true ) ); }
     1032        | FOR '(' push for_control_expression ')' statement
    10611033                { $$ = new StatementNode( build_for( $4, $6 ) ); }
    10621034        ;
    10631035
    10641036for_control_expression:
    1065         comma_expression_opt ';' comma_expression_opt ';' comma_expression_opt
    1066                 { $$ = new ForCtl( $1, $3, $5 ); }
     1037        comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
     1038                { $$ = new ForCtl( $1, $4, $6 ); }
    10671039        | declaration comma_expression_opt ';' comma_expression_opt // C99
    10681040                { $$ = new ForCtl( $1, $2, $4 ); }
     
    11861158
    11871159handler_clause:
    1188         handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
    1189                 { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
    1190         | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
    1191                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
     1160        handler_key '(' push push exception_declaration pop handler_predicate_opt ')' compound_statement pop
     1161                { $$ = new StatementNode( build_catch( $1, $5, $7, $9 ) ); }
     1162        | handler_clause handler_key '(' push push exception_declaration pop handler_predicate_opt ')' compound_statement pop
     1163                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $6, $8, $10 ) ) ); }
    11921164        ;
    11931165
     
    12931265
    12941266declaration_list_opt:                                                                   // used at beginning of switch statement
     1267        pop     // empty
     1268                { $$ = nullptr; }
     1269        | declaration_list
     1270        ;
     1271
     1272declaration_list:
     1273        declaration
     1274        | declaration_list push declaration
     1275                { $$ = $1->appendList( $3 ); }
     1276        ;
     1277
     1278KR_declaration_list_opt:                                                                // used to declare parameter types in K&R style functions
    12951279        // empty
    12961280                { $$ = nullptr; }
    1297         | declaration_list
    1298         ;
    1299 
    1300 declaration_list:
    1301         declaration
    1302         | declaration_list declaration
    1303                 { $$ = $1->appendList( $2 ); }
    1304         ;
    1305 
    1306 KR_parameter_list_opt:                                                                  // used to declare parameter types in K&R style functions
    1307         // empty
    1308                 { $$ = nullptr; }
    1309         | KR_parameter_list
    1310         ;
    1311 
    1312 KR_parameter_list:
     1281        | KR_declaration_list
     1282        ;
     1283
     1284KR_declaration_list:
    13131285        push c_declaration pop ';'
    13141286                { $$ = $2; }
    1315         | KR_parameter_list push c_declaration pop ';'
     1287        | KR_declaration_list push c_declaration pop ';'
    13161288                { $$ = $1->appendList( $3 ); }
    13171289        ;
     
    13331305
    13341306declaration:                                                                                    // old & new style declarations
    1335         c_declaration ';'
    1336         | cfa_declaration ';'                                                           // CFA
    1337         | static_assert                                                                         // C11
     1307        c_declaration pop ';'
     1308        | cfa_declaration pop ';'                                                       // CFA
     1309        | static_assert
    13381310        ;
    13391311
     
    13411313        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    13421314                { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
    1343         | STATICASSERT '(' constant_expression ')' ';'          // CFA
    1344                 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
    13451315
    13461316// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    13871357cfa_function_declaration:                                                               // CFA
    13881358        cfa_function_specifier
     1359                { $$ = $1; }
    13891360        | type_qualifier_list cfa_function_specifier
    13901361                { $$ = $2->addQualifiers( $1 ); }
     
    13931364        | declaration_qualifier_list type_qualifier_list cfa_function_specifier
    13941365                { $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); }
    1395         | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1366        | cfa_function_declaration ',' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
    13961367                {
    13971368                        // Append the return type at the start (left-hand-side) to each identifier in the list.
    13981369                        DeclarationNode * ret = new DeclarationNode;
    13991370                        ret->type = maybeClone( $1->type->base );
    1400                         $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
     1371                        $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $5, nullptr ) );
    14011372                }
    14021373        ;
    14031374
    14041375cfa_function_specifier:                                                                 // CFA
    1405 //      '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
     1376//      '[' ']' identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')' // S/R conflict
    14061377//              {
    14071378//                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );
    14081379//              }
    1409 //      '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1380//      '[' ']' identifier '(' push cfa_parameter_type_list_opt pop ')'
    14101381//              {
    14111382//                      typedefTable.setNextIdentifier( *$5 );
    14121383//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    14131384//              }
    1414 //      | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1385//      | '[' ']' TYPEDEFname '(' push cfa_parameter_type_list_opt pop ')'
    14151386//              {
    14161387//                      typedefTable.setNextIdentifier( *$5 );
     
    14201391                // identifier_or_type_name must be broken apart because of the sequence:
    14211392                //
    1422                 //   '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
     1393                //   '[' ']' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
    14231394                //   '[' ']' type_specifier
    14241395                //
    14251396                // type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be
    14261397                // flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name.
    1427         cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1398        cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
    14281399                // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
    14291400                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); }
    1430         | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
     1401        | cfa_function_return identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
    14311402                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); }
    14321403        ;
     
    14431414        TYPEDEF cfa_variable_specifier
    14441415                {
    1445                         typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "1" );
     1416                        typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname );
    14461417                        $$ = $2->addTypedef();
    14471418                }
    14481419        | TYPEDEF cfa_function_specifier
    14491420                {
    1450                         typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "2" );
     1421                        typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname );
    14511422                        $$ = $2->addTypedef();
    14521423                }
    14531424        | cfa_typedef_declaration pop ',' push no_attr_identifier
    14541425                {
    1455                         typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "3" );
     1426                        typedefTable.addToEnclosingScope( *$5, TYPEDEFname );
    14561427                        $$ = $1->appendList( $1->cloneType( $5 ) );
    14571428                }
     
    14641435        TYPEDEF type_specifier declarator
    14651436                {
    1466                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
     1437                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname );
    14671438                        $$ = $3->addType( $2 )->addTypedef();
    14681439                }
    14691440        | typedef_declaration pop ',' push declarator
    14701441                {
    1471                         typedefTable.addToEnclosingScope( *$5->name, TYPEDEFname, "5" );
     1442                        typedefTable.addToEnclosingScope( *$5->name, TYPEDEFname );
    14721443                        $$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
    14731444                }
    14741445        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
    14751446                {
    1476                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
     1447                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname );
    14771448                        $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
    14781449                }
    14791450        | type_specifier TYPEDEF declarator
    14801451                {
    1481                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
     1452                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname );
    14821453                        $$ = $3->addType( $1 )->addTypedef();
    14831454                }
    14841455        | type_specifier TYPEDEF type_qualifier_list declarator
    14851456                {
    1486                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
     1457                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname );
    14871458                        $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
    14881459                }
     
    16111582
    16121583forall:
    1613         FORALL '(' type_parameter_list ')'                                      // CFA
    1614                 { $$ = DeclarationNode::newForall( $3 ); }
     1584        FORALL '(' push type_parameter_list pop ')'                                     // CFA
     1585                { $$ = DeclarationNode::newForall( $4 ); }
    16151586        ;
    16161587
     
    17941765                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    17951766        | '.' TYPEDEFname
    1796                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1767                { $$ = DeclarationNode::newFromTypedef( $2 ); } // FIX ME
    17971768        | type_name '.' TYPEDEFname
    1798                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1769                { $$ = DeclarationNode::newFromTypedef( $3 ); } // FIX ME
    17991770        | typegen_name
    18001771        | '.' typegen_name
    1801                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1772                { $$ = $2; }                                                                    // FIX ME
    18021773        | type_name '.' typegen_name
    1803                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1774                { $$ = $3; }                                                                    // FIX ME
    18041775        ;
    18051776
     
    18231794        ;
    18241795
    1825 fred:
    1826         // empty
    1827                 { yyy = false; }
    1828         ;
    1829 
    18301796aggregate_type:                                                                                 // struct, union
    18311797        aggregate_key attribute_list_opt '{' field_declaration_list_opt '}'
    18321798                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), nullptr, $4, true )->addQualifiers( $2 ); }
    1833         | aggregate_key attribute_list_opt no_attr_identifier fred
    1834                 {
    1835                         typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname ); // create typedef
    1836                         //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
     1799        | aggregate_key attribute_list_opt no_attr_identifier_or_type_name
     1800                {
     1801                        typedefTable.makeTypedef( *$3 );                        // create typedef
     1802                        if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    18371803                        forall = false;                                                         // reset
    18381804                }
    18391805          '{' field_declaration_list_opt '}'
    1840                 { $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $7, true )->addQualifiers( $2 ); }
    1841         | aggregate_key attribute_list_opt type_name fred
    1842                 {
    1843                         typedefTable.makeTypedef( *$3->type->symbolic.name, forall ? TYPEGENname : TYPEDEFname ); // create typedef
    1844                         //if ( forall ) typedefTable.changeKind( *$3->type->symbolic.name, TYPEGENname ); // possibly update
    1845                         forall = false;                                                         // reset
    1846                 }
    1847           '{' field_declaration_list_opt '}'
    1848                 { $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, nullptr, $7, true )->addQualifiers( $2 ); }
     1806                { $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $6, true )->addQualifiers( $2 ); }
    18491807        | aggregate_key attribute_list_opt '(' type_list ')' '{' field_declaration_list_opt '}' // CFA
    18501808                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), $4, $7, false )->addQualifiers( $2 ); }
     
    18531811
    18541812aggregate_type_nobody:                                                                  // struct, union - {...}
    1855         aggregate_key attribute_list_opt no_attr_identifier fred
    1856                 {
    1857                         typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname );
    1858                         //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
     1813        aggregate_key attribute_list_opt no_attr_identifier
     1814                {
     1815                        typedefTable.makeTypedef( *$3 );
     1816                        if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    18591817                        forall = false;                                                         // reset
    18601818                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    18611819                }
    1862         | aggregate_key attribute_list_opt type_name fred
     1820        | aggregate_key attribute_list_opt TYPEDEFname
     1821                {
     1822                        typedefTable.makeTypedef( *$3 );
     1823                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
     1824                }
     1825        | aggregate_key attribute_list_opt typegen_name         // CFA
    18631826                {
    18641827                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
     
    18741837aggregate_key:
    18751838        STRUCT
    1876                 { yyy = true; $$ = DeclarationNode::Struct; }
     1839                { $$ = DeclarationNode::Struct; }
    18771840        | UNION
    1878                 { yyy = true; $$ = DeclarationNode::Union; }
     1841                { $$ = DeclarationNode::Union; }
    18791842        | EXCEPTION
    1880                 { yyy = true; $$ = DeclarationNode::Exception; }
     1843                { $$ = DeclarationNode::Exception; }
    18811844        | COROUTINE
    1882                 { yyy = true; $$ = DeclarationNode::Coroutine; }
     1845                { $$ = DeclarationNode::Coroutine; }
    18831846        | MONITOR
    1884                 { yyy = true; $$ = DeclarationNode::Monitor; }
     1847                { $$ = DeclarationNode::Monitor; }
    18851848        | THREAD
    1886                 { yyy = true; $$ = DeclarationNode::Thread; }
     1849                { $$ = DeclarationNode::Thread; }
    18871850        ;
    18881851
     
    18951858
    18961859field_declaration:
    1897         type_specifier field_declaring_list ';'
    1898                 { $$ = distAttr( $1, $2 ); }
     1860        cfa_field_declaring_list ';'                                            // CFA, new style field declaration
     1861        | EXTENSION cfa_field_declaring_list ';'                        // GCC
     1862                {
     1863                        distExt( $2 );                                                          // mark all fields in list
     1864                        $$ = $2;
     1865                }
     1866        | type_specifier field_declaring_list ';'
     1867                {
     1868                        $$ = distAttr( $1, $2 ); }
    18991869        | EXTENSION type_specifier field_declaring_list ';'     // GCC
    1900                 { distExt( $3 ); $$ = distAttr( $2, $3 ); }             // mark all fields in list
    1901         | typedef_declaration ';'                                                       // CFA
    1902                 { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    1903         | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
    1904         | EXTENSION cfa_field_declaring_list ';'                        // GCC
    1905                 { distExt( $2 ); $$ = $2; }                                             // mark all fields in list
    1906         | cfa_typedef_declaration ';'                                           // CFA
    1907                 { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    1908         | static_assert                                                                         // C11
     1870                {
     1871                        distExt( $3 );                                                          // mark all fields in list
     1872                        $$ = distAttr( $2, $3 );
     1873                }
     1874        | static_assert
    19091875        ;
    19101876
     
    19451911                { $$ = nullptr; }
    19461912        | bit_subrange_size
     1913                { $$ = $1; }
    19471914        ;
    19481915
     
    19551922        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    19561923                { $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
    1957         | ENUM attribute_list_opt no_attr_identifier
     1924        | ENUM attribute_list_opt no_attr_identifier_or_type_name
    19581925                { typedefTable.makeTypedef( *$3 ); }
    19591926          '{' enumerator_list comma_opt '}'
    19601927                { $$ = DeclarationNode::newEnum( $3, $6, true )->addQualifiers( $2 ); }
    1961         | ENUM attribute_list_opt type_name
    1962           '{' enumerator_list comma_opt '}'
    1963                 { $$ = DeclarationNode::newEnum( $3->type->symbolic.name, $5, true )->addQualifiers( $2 ); }
    19641928        | enum_type_nobody
    19651929        ;
    19661930
    19671931enum_type_nobody:                                                                               // enum - {...}
    1968         ENUM attribute_list_opt no_attr_identifier
     1932        ENUM attribute_list_opt no_attr_identifier_or_type_name
    19691933                {
    19701934                        typedefTable.makeTypedef( *$3 );
    19711935                        $$ = DeclarationNode::newEnum( $3, 0, false )->addQualifiers( $2 );
    1972                 }
    1973         | ENUM attribute_list_opt type_name
    1974                 {
    1975                         typedefTable.makeTypedef( *$3->type->symbolic.name );
    1976                         $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false )->addQualifiers( $2 );
    19771936                }
    19781937        ;
     
    19921951        ;
    19931952
    1994 cfa_parameter_ellipsis_list_opt:                                                        // CFA, abstract + real
     1953cfa_parameter_type_list_opt:                                                    // CFA, abstract + real
    19951954        // empty
    19961955                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     
    21252084                { $$ = $2; }
    21262085        | '=' VOID
    2127                 { $$ = new InitializerNode( true ); }
     2086                { $$ = nullptr; }
    21282087        | ATassign initializer
    21292088                { $$ = $2->set_maybeConstructed( false ); }
     
    22022161type_parameter_list:                                                                    // CFA
    22032162        type_parameter
     2163                { $$ = $1; }
    22042164        | type_parameter_list ',' type_parameter
    22052165                { $$ = $1->appendList( $3 ); }
     
    22152175type_parameter:                                                                                 // CFA
    22162176        type_class no_attr_identifier_or_type_name
    2217                 { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
     2177                { typedefTable.addToEnclosingScope( *$2, TYPEDEFname ); }
    22182178          type_initializer_opt assertion_list_opt
    22192179                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
     
    22492209        '|' no_attr_identifier_or_type_name '(' type_list ')'
    22502210                { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
    2251         | '|' '{' push trait_declaration_list pop '}'
     2211        | '|' '{' push trait_declaration_list '}'
    22522212                { $$ = $4; }
    2253         // | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' '(' type_list ')'
    2254         //      { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
     2213        | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list '}' '(' type_list ')'
     2214                { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
    22552215        ;
    22562216
     
    22842244        no_attr_identifier_or_type_name
    22852245                {
    2286                         typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
     2246                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname );
    22872247                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    22882248                }
    2289         | no_attr_identifier_or_type_name '(' type_parameter_list ')'
    2290                 {
    2291                         typedefTable.addToEnclosingScope( *$1, TYPEGENname, "11" );
    2292                         $$ = DeclarationNode::newTypeDecl( $1, $3 );
     2249        | no_attr_identifier_or_type_name '(' push type_parameter_list pop ')'
     2250                {
     2251                        typedefTable.addToEnclosingScope( *$1, TYPEGENname );
     2252                        $$ = DeclarationNode::newTypeDecl( $1, $4 );
    22932253                }
    22942254        ;
    22952255
    22962256trait_specifier:                                                                                // CFA
    2297         TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    2298                 { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
    2299         | TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    2300                 { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
     2257        TRAIT no_attr_identifier_or_type_name '(' push type_parameter_list pop ')' '{' '}'
     2258                { $$ = DeclarationNode::newTrait( $2, $5, 0 ); }
     2259        | TRAIT no_attr_identifier_or_type_name '(' push type_parameter_list pop ')' '{' push trait_declaration_list '}'
     2260                { $$ = DeclarationNode::newTrait( $2, $5, $10 ); }
    23012261        ;
    23022262
    23032263trait_declaration_list:                                                                 // CFA
    23042264        trait_declaration
    2305         | trait_declaration_list pop push trait_declaration
    2306                 { $$ = $1->appendList( $4 ); }
     2265        | trait_declaration_list push trait_declaration
     2266                { $$ = $1->appendList( $3 ); }
    23072267        ;
    23082268
    23092269trait_declaration:                                                                              // CFA
    2310         cfa_trait_declaring_list ';'
    2311         | trait_declaring_list ';'
     2270        cfa_trait_declaring_list pop ';'
     2271        | trait_declaring_list pop ';'
    23122272        ;
    23132273
     
    23292289
    23302290translation_unit:
    2331         // empty, input file
     2291        // empty
     2292                {}                                                                                              // empty input file
    23322293        | external_definition_list
    23332294                { parseTree = parseTree ? parseTree->appendList( $1 ) : $1;     }
     
    23352296
    23362297external_definition_list:
    2337         push external_definition pop
    2338                 { $$ = $2; }
     2298        external_definition
    23392299        | external_definition_list
    23402300                { forall = xxx; }
    2341           push external_definition pop
     2301          push external_definition
    23422302                { $$ = $1 ? $1->appendList( $4 ) : $4; }
    23432303        ;
     
    23492309        ;
    23502310
    2351 up:
    2352                 { typedefTable.up(); }
    2353         ;
    2354 
    2355 down:
    2356                 { typedefTable.down(); }
    2357         ;
    2358 
    23592311external_definition:
    23602312        declaration
    23612313        | external_function_definition
     2314        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
     2315                {
     2316                        $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) );
     2317                }
     2318        | EXTERN STRINGliteral                                                          // C++-style linkage specifier
     2319                {
     2320                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
     2321                        linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
     2322                }
     2323          '{' external_definition_list_opt '}'
     2324                {
     2325                        linkage = linkageStack.top();
     2326                        linkageStack.pop();
     2327                        $$ = $5;
     2328                }
    23622329        | EXTENSION external_definition                                         // GCC, multiple __extension__ allowed, meaning unknown
    23632330                {
     
    23652332                        $$ = $2;
    23662333                }
    2367         | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    2368                 {
    2369                         $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) );
    2370                 }
    2371         | EXTERN STRINGliteral                                                          // C++-style linkage specifier
    2372                 {
    2373                         linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    2374                         linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
    2375                 }
    2376           '{' up external_definition_list_opt down '}'
    2377                 {
    2378                         linkage = linkageStack.top();
    2379                         linkageStack.pop();
    2380                         $$ = $6;
    2381                 }
    23822334        | type_qualifier_list
    2383                 {
    2384                         if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2385                         if ( $1->type->forall ) xxx = forall = true; // remember generic type
    2386                 }
    2387           '{' up external_definition_list_opt down '}'          // CFA, namespace
     2335                { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
     2336          push '{' external_definition_list '}'                         // CFA, namespace
    23882337                {
    23892338                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    23972346                }
    23982347        | declaration_qualifier_list
    2399                 {
    2400                         if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2401                         if ( $1->type->forall ) xxx = forall = true; // remember generic type
    2402                 }
    2403           '{' up external_definition_list_opt down '}'          // CFA, namespace
     2348                { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
     2349          push '{' external_definition_list '}'                         // CFA, namespace
    24042350                {
    24052351                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    24142360        | declaration_qualifier_list type_qualifier_list
    24152361                {
    2416                         if ( ($1->type && $1->type->qualifiers.val) || $2->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2417                         if ( ($1->type && $1->type->forall) || $2->type->forall ) xxx = forall = true; // remember generic type
    2418                 }
    2419           '{' up external_definition_list_opt down '}'          // CFA, namespace
     2362                        // forall must be in the type_qualifier_list
     2363                        if ( $2->type->forall ) xxx = forall = true; // remember generic type
     2364                }
     2365          push '{' external_definition_list '}'                         // CFA, namespace
    24202366                {
    24212367                        for ( DeclarationNode * iter = $6; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    24412387        | function_declarator compound_statement
    24422388                { $$ = $1->addFunctionBody( $2 ); }
    2443         | KR_function_declarator KR_parameter_list_opt compound_statement
     2389        | KR_function_declarator KR_declaration_list_opt compound_statement
    24442390                { $$ = $1->addOldDeclList( $2 )->addFunctionBody( $3 ); }
    24452391        ;
     
    24812427
    24822428                // Old-style K&R function definition, OBSOLESCENT (see 4)
    2483         | declaration_specifier KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
     2429        | declaration_specifier KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24842430                {
    24852431                        rebindForall( $1, $2 );
     
    24872433                }
    24882434                // handles default int return type, OBSOLESCENT (see 1)
    2489         | type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
     2435        | type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24902436                { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
    24912437                // handles default int return type, OBSOLESCENT (see 1)
    2492         | declaration_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
     2438        | declaration_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24932439                { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
    24942440                // handles default int return type, OBSOLESCENT (see 1)
    2495         | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
     2441        | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24962442                { $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 ); }
    24972443        ;
     
    27382684        typedef
    27392685                // hide type name in enclosing scope by variable name
    2740                 { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "ID" ); }
     2686                { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER ); }
    27412687        | '(' paren_type ')'
    27422688                { $$ = $2; }
     
    30282974        '[' ']'
    30292975                { $$ = DeclarationNode::newArray( 0, 0, false ); }
    3030                 // multi_array_dimension handles the '[' '*' ']' case
     2976        // multi_array_dimension handles the '[' '*' ']' case
    30312977        | '[' push type_qualifier_list '*' pop ']'                      // remaining C99
    30322978                { $$ = DeclarationNode::newVarArray( $3 ); }
    30332979        | '[' push type_qualifier_list pop ']'
    30342980                { $$ = DeclarationNode::newArray( 0, $3, false ); }
    3035                 // multi_array_dimension handles the '[' assignment_expression ']' case
     2981        // multi_array_dimension handles the '[' assignment_expression ']' case
    30362982        | '[' push type_qualifier_list assignment_expression pop ']'
    30372983                { $$ = DeclarationNode::newArray( $4, $3, false ); }
     
    31693115//
    31703116//              cfa_abstract_tuple identifier_or_type_name
    3171 //              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
     3117//              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
    31723118//
    31733119// since a function return type can be syntactically identical to a tuple type:
     
    32283174        '[' push cfa_abstract_parameter_list pop ']'
    32293175                { $$ = DeclarationNode::newTuple( $3 ); }
    3230         | '[' push type_specifier_nobody ELLIPSIS pop ']'
    3231                 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; }
    3232         | '[' push type_specifier_nobody ELLIPSIS constant_expression pop ']'
    3233                 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; }
    32343176        ;
    32353177
    32363178cfa_abstract_function:                                                                  // CFA
    3237 //      '[' ']' '(' cfa_parameter_ellipsis_list_opt ')'
     3179//      '[' ']' '(' cfa_parameter_type_list_opt ')'
    32383180//              { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
    3239         cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')'
     3181        cfa_abstract_tuple '(' push cfa_parameter_type_list_opt pop ')'
    32403182                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    3241         | cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')'
     3183        | cfa_function_return '(' push cfa_parameter_type_list_opt pop ')'
    32423184                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    32433185        ;
     
    32703212
    32713213%%
    3272 
    32733214// ----end of grammar----
    32743215
  • src/ResolvExpr/Alternative.cc

    rb21c77a r97397a26  
    3030
    3131namespace ResolvExpr {
    32         Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
     32        Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( 0 ) {}
    3333
    3434        Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
  • src/ResolvExpr/AlternativeFinder.cc

    rb21c77a r97397a26  
    100100                void postvisit( InitExpr * initExpr );
    101101                void postvisit( DeletedExpr * delExpr );
    102                 void postvisit( GenericExpr * genExpr );
    103102
    104103                /// Adds alternatives for anonymous members
     
    178177                                                selected[ mangleName ] = current;
    179178                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    180                                                 // if one of the candidates contains a deleted identifier, can pick the other, since
    181                                                 // deleted expressions should not be ambiguous if there is another option that is at least as good
    182                                                 if ( findDeletedExpr( candidate->expr ) ) {
    183                                                         // do nothing
    184                                                         PRINT( std::cerr << "candidate is deleted" << std::endl; )
    185                                                 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
    186                                                         PRINT( std::cerr << "current is deleted" << std::endl; )
    187                                                         selected[ mangleName ] = current;
    188                                                 } else {
    189                                                         PRINT(
    190                                                                 std::cerr << "marking ambiguous" << std::endl;
    191                                                         )
    192                                                         mapPlace->second.isAmbiguous = true;
    193                                                 }
     179                                                PRINT(
     180                                                        std::cerr << "marking ambiguous" << std::endl;
     181                                                )
     182                                                mapPlace->second.isAmbiguous = true;
    194183                                        } else {
    195184                                                PRINT(
     
    311300                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
    312301                Expression* aggrExpr = alt.expr->clone();
    313                 alt.env.apply( aggrExpr->result );
    314                 Type * aggrType = aggrExpr->result;
     302                alt.env.apply( aggrExpr->get_result() );
     303                Type * aggrType = aggrExpr->get_result();
    315304                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    316305                        aggrType = aggrType->stripReferences();
     
    318307                }
    319308
    320                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
     309                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    321310                        addAggMembers( structInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
    322                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
     311                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    323312                        addAggMembers( unionInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
    324313                } // if
     
    330319                aggInst->lookup( name, members );
    331320
    332                 for ( Declaration * decl : members ) {
    333                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
    334                                 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    335                                 // can't construct in place and use vector::back
    336                                 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
    337                                 renameTypes( newAlt.expr );
    338                                 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
    339                                 alternatives.push_back( std::move(newAlt) );
     321                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
     322                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
     323                                alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
     324                                renameTypes( alternatives.back().expr );
     325                                addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
    340326                        } else {
    341327                                assert( false );
     
    347333                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    348334                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    349                         auto val = constantExpr->intValue();
     335                        // xxx - this should be improved by memoizing the value of constant exprs
     336                        // during parsing and reusing that information here.
     337                        std::stringstream ss( constantExpr->get_constant()->get_value() );
     338                        int val = 0;
    350339                        std::string tmp;
    351                         if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    352                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
     340                        if ( ss >> val && ! (ss >> tmp) ) {
     341                                if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
     342                                        alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
     343                                } // if
    353344                        } // if
     345                } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
     346                        // xxx - temporary hack until 0/1 are int constants
     347                        if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
     348                                std::stringstream ss( nameExpr->get_name() );
     349                                int val;
     350                                ss >> val;
     351                                alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
     352                        }
    354353                } // if
    355354        }
     
    438437                                        return Cost::infinity;
    439438                                }
    440                         }
    441                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
    442                                 // default arguments should be free - don't include conversion cost.
    443                                 // Unwrap them here because they are not relevant to the rest of the system.
    444                                 *actualExpr = def->expr;
    445                                 ++formal;
    446                                 continue;
    447439                        }
    448440                        Type * formalType = (*formal)->get_type();
     
    772764        ConstantExpr* getDefaultValue( Initializer* init ) {
    773765                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    774                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
    775                                 return dynamic_cast<ConstantExpr*>( ce->arg );
    776                         } else {
    777                                 return dynamic_cast<ConstantExpr*>( si->value );
     766                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
     767                                return dynamic_cast<ConstantExpr*>( ce->get_arg() );
    778768                        }
    779769                }
     
    10361026                                                                indexer ) ) {
    10371027                                                        results.emplace_back(
    1038                                                                 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
     1028                                                                i, cnstExpr, move(env), move(need), move(have),
    10391029                                                                move(openVars), nextArg, nTuples );
    10401030                                                }
     
    13691359                funcFinder.findWithAdjustment( untypedExpr->function );
    13701360                // if there are no function alternatives, then proceeding is a waste of time.
    1371                 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    13721361                if ( funcFinder.alternatives.empty() ) return;
    13731362
     
    13971386                        argExpansions.emplace_back();
    13981387                        auto& argE = argExpansions.back();
    1399                         // argE.reserve( arg.alternatives.size() );
     1388                        argE.reserve( arg.alternatives.size() );
    14001389
    14011390                        for ( const Alternative& actual : arg ) {
     
    14201409                                                        std::back_inserter( candidates ) );
    14211410                                        }
    1422                                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    1423                                         if ( ClassRef eqvClass = func->env.lookup( typeInst->name ) ) {
     1411                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     1412                                        if ( ClassRef eqvClass = func->env.lookup( typeInst->get_name() ) ) {
    14241413                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.get_bound().type ) ) {
    14251414                                                        Alternative newFunc( *func );
     
    16761665                        Cost cost = Cost::zero;
    16771666                        Expression * newExpr = data.combine( cost );
    1678 
    1679                         // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    1680                         // can't construct in place and use vector::back
    1681                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1667                        alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    16821668                        PRINT(
    16831669                                std::cerr << "decl is ";
     
    16881674                                std::cerr << std::endl;
    16891675                        )
    1690                         renameTypes( newAlt.expr );
    1691                         addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
    1692                         alternatives.push_back( std::move(newAlt) );
     1676                        renameTypes( alternatives.back().expr );
     1677                        addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
    16931678                } // for
    16941679        }
     
    20572042                assertf( false, "AlternativeFinder should never see a DeletedExpr." );
    20582043        }
    2059 
    2060         void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
    2061                 assertf( false, "_Generic is not yet supported." );
    2062         }
    20632044} // namespace ResolvExpr
    20642045
  • src/ResolvExpr/CommonType.cc

    rb21c77a r97397a26  
    2424#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2525#include "SynTree/Visitor.h"             // for Visitor
    26 #include "Unify.h"                       // for unifyExact, WidenMode
     26#include "Unify.h"                       // for unifyExact, bindVar, WidenMode
    2727#include "typeops.h"                     // for isFtype
    2828
     
    176176        }
    177177
    178         static const BasicType::Kind combinedType[][ BasicType::NUMBER_OF_BASIC_TYPES ] =
     178        static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
    179179        {
    180 /*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128   Float80   Float128 */
    181                 /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    182                 /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    183                 /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    184                 /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    185                 /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    186                 /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    187                 /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    188                 /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    189                 /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    190                 /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    191                 /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    192                 /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
    193                 /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, BasicType::Float80, BasicType::Float128 },
    194                 /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, BasicType::Float80, BasicType::Float128 },
    195                 /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, BasicType::BasicType::LongDouble, BasicType::Float128 },
    196                 /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
    197                 /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex },
    198                 /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
    199                 /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
    200                 /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
    201                 /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
    202                 /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
    203                 /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
    204                 /* Float80 */   { BasicType::Float80,   BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float80,     BasicType::Float80, BasicType::Float80, BasicType::Float128 },
    205                 /* Float128 */  { BasicType::Float128,  BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float128,    BasicType::Float128, BasicType::Float128, BasicType::Float128 },
     180/*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128 */
     181                /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     182                /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     183                /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     184                /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     185                /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     186                /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     187                /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     188                /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     189                /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     190                /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     191                /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     192                /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     193                /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, },
     194                /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, },
     195                /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, },
     196                /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, },
     197                /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, },
     198                /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, },
     199                /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, },
     200                /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, },
     201                /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary },
     202                /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     203                /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, },
    206204        };
    207         static_assert(
    208                 sizeof(combinedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
    209                 "Each basic type kind should have a corresponding row in the combined type matrix"
    210         );
    211205
    212206        CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     
    238232                                AssertionSet need, have;
    239233                                WidenMode widen( widenFirst, widenSecond );
    240                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
     234                                if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
    241235                        }
    242236                }
  • src/ResolvExpr/ConversionCost.cc

    rb21c77a r97397a26  
    231231*/
    232232
    233         static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
    234         /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128, F80, F128 */
    235                 /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,       14,   15},
    236                 /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
    237                 /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
    238                 /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,        12,   13},
    239                 /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,        11,   12},
    240                 /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,        10,   11},
    241                 /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,        9,    10},
    242                 /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
    243                 /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
    244                 /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,        7,    8},
    245                 /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,        6,    7},
    246                 /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,        5,    6},
    247 
    248                 /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,       2,    3},
    249                 /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,       1,    2},
    250                 /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   1},
    251                 /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
    252                 /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
    253                 /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
    254                 /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,       -1,   -1},
    255                 /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,       -1,   -1},
    256                 /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,       -1,   -1},
    257 
    258                 /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,        4,    4},
    259                 /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,        3,    3},
    260 
    261                 /* F80 */       { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       0,    1},
    262                 /* F128 */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   0},
     233        static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
     234        /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128 */
     235                /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,     },
     236                /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
     237                /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
     238                /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,      },
     239                /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,      },
     240                /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,      },
     241                /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,      },
     242                /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
     243                /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
     244                /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,      },
     245                /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,      },
     246                /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,      },
     247
     248                /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,     },
     249                /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,     },
     250                /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,     },
     251                /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,     },
     252                /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,     },
     253                /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,     },
     254                /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,     },
     255                /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,     },
     256                /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,     },
     257
     258                /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,      },
     259                /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,      },
    263260        };
    264         static_assert(
    265                 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
    266                 "Each basic type kind should have a corresponding row in the cost matrix"
    267         );
    268 
    269261
    270262        void ConversionCost::postvisit( VoidType * ) {
  • src/ResolvExpr/ExplodedActual.h

    rb21c77a r97397a26  
    3131
    3232                ExplodedActual() : env(), cost(Cost::zero), exprs() {}
     33
    3334                ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
    34                 ExplodedActual(ExplodedActual&&) = default;
    35                 ExplodedActual& operator= (ExplodedActual&&) = default;
    3635        };
    3736}
  • src/ResolvExpr/Resolver.cc

    rb21c77a r97397a26  
    217217                        if ( findDeletedExpr( choice.expr ) ) {
    218218                                trace( choice.expr );
    219                                 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
     219                                SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
    220220                        }
    221221                        alt = std::move( choice );
     
    252252
    253253                auto untyped = new CastExpr{ expr }; // cast to void
    254                 untyped->location = expr->location;
    255254
    256255                // set up and resolve expression cast to void
     
    278277        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    279278                assert( untyped && type );
    280                 // transfer location to generated cast for error purposes
    281                 CodeLocation location = untyped->location;
    282279                untyped = new CastExpr( untyped, type );
    283                 untyped->location = location;
    284280                findSingleExpression( untyped, indexer );
    285281                removeExtraneousCast( untyped, indexer );
     
    584580
    585581                                                        // Make sure we don't widen any existing bindings
    586                                                         resultEnv.forbidWidening();
    587                                                        
     582                                                        for ( auto & i : resultEnv ) {
     583                                                                i.allowWidening = false;
     584                                                        }
     585
    588586                                                        // Find any unbound type variables
    589587                                                        resultEnv.extractOpenVars( openVars );
  • src/ResolvExpr/Resolver.h

    rb21c77a r97397a26  
    3636        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3737        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
    38         /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    39         DeletedExpr * findDeletedExpr( Expression * expr );
    4038} // namespace ResolvExpr
    4139
  • src/ResolvExpr/TypeEnvironment.cc

    rb21c77a r97397a26  
    77// TypeEnvironment.cc --
    88//
    9 // Author           : Aaron B. Moss
     9// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Jun 29 15:51:00 2018
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May 17 12:23:36 2015
     13// Update Count     : 3
    1414//
    1515
     
    2727#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    2828#include "TypeEnvironment.h"
    29 #include "typeops.h"                   // for occurs
    3029#include "Unify.h"                     // for unifyInexact
    3130
     
    5150#if 0
    5251        void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {
    53                 initialize( src, dest, src.type );
    54         }
    55 
    56         void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {
    5752                dest.vars = src.vars;
    58                 dest.type = maybeClone( ty );
     53                dest.type = maybeClone( src.type );
    5954                dest.allowWidening = src.allowWidening;
    6055                dest.data = src.data;
    6156        }
    6257
    63         EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) {
    64         }
     58        EqvClass::EqvClass() : vars(), type( 0 ), allowWidening( true ), data() {}
     59
     60        EqvClass::EqvClass( std::vector<interned_string>&& vs, BoundType&& bound )
     61                : vars( vs.begin(), vs.end() ), type( maybeClone( bound.type ) ),
     62                  allowWidening( bound.allowWidening ), data( bound.data ) {}
    6563
    6664        EqvClass::EqvClass( const EqvClass &other ) {
    6765                initialize( other, *this );
    68         }
    69 
    70         EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {
    71                 initialize( other, *this, ty );
    72         }
    73 
    74         EqvClass::EqvClass( EqvClass &&other )
    75         : vars{std::move(other.vars)}, type{other.type},
    76           allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
    77                   other.type = nullptr;
    7866        }
    7967
     
    8371                return *this;
    8472        }
    85 
    86         EqvClass &EqvClass::operator=( EqvClass &&other ) {
    87                 if ( this == &other ) return *this;
    88                
    89                 vars = std::move(other.vars);
    90                 type = other.type;
    91                 allowWidening = std::move(other.allowWidening);
    92                 data = std::move(other.data);
    93 
    94                 return *this;
    95         }
    96 
    97         void EqvClass::set_type( Type* ty ) { type = ty; }
    9873
    9974        void EqvClass::print( std::ostream &os, Indenter indent ) const {
     
    11388        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    11489                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    115                         if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     90                        if ( i->vars.find( var ) != i->vars.end() ) {
     91///       std::cout << var << " is in class ";
     92///       i->print( std::cout );
     93                                return &*i;
     94                        }
     95///     std::cout << var << " is not in class ";
     96///     i->print( std::cout );
    11697                } // for
    11798                return nullptr;
     
    137118                if ( root ) return { this, root };
    138119                else return { nullptr, var };
    139         }
    140 
    141         bool isFtype( Type *type ) {
    142                 if ( dynamic_cast< FunctionType* >( type ) ) {
    143                         return true;
    144                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    145                         return typeInst->get_isFtype();
    146                 } // if
    147                 return false;
    148120        }
    149121
     
    316288        }
    317289
     290        void TypeEnvironment::add( const EqvClass &eqvClass ) {
     291                filterOverlappingClasses( env, eqvClass );
     292                env.push_back( eqvClass );
     293        }
     294
    318295        void TypeEnvironment::add( EqvClass &&eqvClass ) {
    319296                filterOverlappingClasses( env, eqvClass );
     
    326303                        newClass.vars.insert( (*i)->get_name() );
    327304                        newClass.data = TypeDecl::Data{ (*i) };
    328                         env.push_back( std::move(newClass) );
     305                        env.push_back( newClass );
    329306                } // for
    330307        }
     
    340317                        // transition to TypeSubstitution
    341318                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
    342                         add( std::move(newClass) );
     319                        add( newClass );
    343320                }
    344321        }
     
    347324                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    348325                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
     326///       std::cerr << "adding " << *theVar;
    349327                                if ( theClass->type ) {
     328///         std::cerr << " bound to ";
     329///         theClass->type->print( std::cerr );
     330///         std::cerr << std::endl;
    350331                                        sub.add( *theVar, theClass->type );
    351332                                } else if ( theVar != theClass->vars.begin() ) {
    352333                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
     334///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    353335                                        sub.add( *theVar, newTypeInst );
    354336                                } // if
    355337                        } // for
    356338                } // for
     339///   std::cerr << "input env is:" << std::endl;
     340///   print( std::cerr, 8 );
     341///   std::cerr << "sub is:" << std::endl;
     342///   sub.print( std::cerr, 8 );
    357343                sub.normalize();
    358344        }
    359345
    360346        void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
    361                 for ( const EqvClass & theClass : env ) {
    362                         theClass.print( os, indent );
     347                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
     348                        i->print( os, indent );
    363349                } // for
    364350        }
     
    366352        std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    367353                for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
    368                         if ( i->vars.count( var ) ) return i;
     354                        if ( i->vars.find( var ) == i->vars.end() ) {
     355                                return i;
     356                        } // if
    369357                } // for
    370358                return env.end();
  • src/ResolvExpr/TypeEnvironment.h

    rb21c77a r97397a26  
    1010// Created On       : Sun May 17 12:24:58 2015
    1111// Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Jun 29 16:00:00 2018
    13 // Update Count     : 5
     12// Last Modified On : Wed Jun 13 16:31:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2424#include <utility>                         // for pair
    2525#include <vector>                          // for vector
    26 
    27 #include "WidenMode.h"                 // for WidenMode
    2826
    2927#include "Common/InternedString.h"         // for interned_string
     
    9795
    9896                void initialize( const EqvClass &src, EqvClass &dest );
    99                 void initialize( const EqvClass &src, EqvClass &dest, const Type *ty );
    10097                EqvClass();
     98                EqvClass( std::vector<interned_string>&& vars, BoundType&& bound );
    10199                EqvClass( const EqvClass &other );
    102                 EqvClass( const EqvClass &other, const Type *ty );
    103                 EqvClass( EqvClass &&other );
    104100                EqvClass &operator=( const EqvClass &other );
    105                 EqvClass &operator=( EqvClass &&other );
    106101                void print( std::ostream &os, Indenter indent = {} ) const;
    107 
    108                 /// Takes ownership of `ty`, freeing old `type`
    109                 void set_type(Type* ty);
    110         };
    111 #endif
    112        
     102        };
     103#endif
     104
    113105        class TypeEnvironment;
    114106
     
    214206                        WidenMode widenMode, const SymTab::Indexer& indexer );
    215207#if !1
    216         private:
    217                 void add( EqvClass &&eqvClass );
    218         public:
     208                void add( const EqvClass &eqvClass );
     209                void add( EqvClass &&eqvClass  );
    219210                void add( const Type::ForallList &tyDecls );
    220211                void add( const TypeSubstitution & sub );
     
    235226                /// and extracts open variables.
    236227                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    237 
    238                 /// Disallows widening for all bindings in the environment
    239                 void forbidWidening();
    240228#endif
    241229
    242230                iterator begin() { return { this, bindings->begin() }; }
    243231                iterator end() { return { this, bindings->end() }; }
     232#if 0
     233                typedef std::list< EqvClass >::const_iterator const_iterator;
     234                const_iterator begin() const { return env.begin(); }
     235                const_iterator end() const { return env.end(); }
     236#endif
    244237        };
    245238
  • src/ResolvExpr/Unify.cc

    rb21c77a r97397a26  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 43
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Mar 16 16:22:54 2017
     13// Update Count     : 42
    1414//
    1515
     
    122122        }
    123123
     124        bool isFtype( Type *type ) {
     125                if ( dynamic_cast< FunctionType* >( type ) ) {
     126                        return true;
     127                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
     128                        return typeInst->get_isFtype();
     129                } // if
     130                return false;
     131        }
     132
     133        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     134                // remove references from other, so that type variables can only bind to value types
     135                other = other->stripReferences();
     136                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
     137                assert( tyvar != openVars.end() );
     138                if ( ! tyVarCompatible( tyvar->second, other ) ) {
     139                        return false;
     140                } // if
     141                if ( occurs( other, typeInst->get_name(), env ) ) {
     142                        return false;
     143                } // if
     144                if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
     145                        if ( curClass->type ) {
     146                                Type *common = 0;
     147                                // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
     148                                Type* newType = curClass->type->clone();
     149                                newType->get_qualifiers() = typeInst->get_qualifiers();
     150                                if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     151                                        if ( common ) {
     152                                                common->get_qualifiers() = Type::Qualifiers();
     153                                                EqvClass newClass = *curClass;
     154                                                newClass.type = common;
     155                                                env.add( std::move(newClass) );
     156                                        } // if
     157                                        return true;
     158                                } else {
     159                                        return false;
     160                                } // if
     161                        } else {
     162                                EqvClass newClass = *curClass;
     163                                newClass.type = other->clone();
     164                                newClass.type->get_qualifiers() = Type::Qualifiers();
     165                                newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     166                                env.add( std::move(newClass) );
     167                        } // if
     168                } else {
     169                        EqvClass newClass;
     170                        newClass.vars.insert( typeInst->get_name() );
     171                        newClass.type = other->clone();
     172                        newClass.type->get_qualifiers() = Type::Qualifiers();
     173                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     174                        newClass.data = data;
     175                        env.add( newClass );
     176                } // if
     177                return true;
     178        }
     179
     180        bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     181                bool result = true;
     182                const EqvClass *class1 = env.lookup( var1->get_name() );
     183                const EqvClass *class2 = env.lookup( var2->get_name() );
     184                bool widen1 = false, widen2 = false;
     185                Type *type1 = nullptr, *type2 = nullptr;
     186
     187                if ( class1 ) {
     188                        if ( class1->type ) {
     189                                if ( occurs( class1->type, var2->get_name(), env ) ) {
     190                                        return false;
     191                                } // if
     192                                type1 = class1->type->clone();
     193                        } // if
     194                        widen1 = widenMode.widenFirst && class1->allowWidening;
     195                } // if
     196                if ( class2 ) {
     197                        if ( class2->type ) {
     198                                if ( occurs( class2->type, var1->get_name(), env ) ) {
     199                                        return false;
     200                                } // if
     201                                type2 = class2->type->clone();
     202                        } // if
     203                        widen2 = widenMode.widenSecond && class2->allowWidening;
     204                } // if
     205
     206                if ( type1 && type2 ) {
     207//    std::cerr << "has type1 && type2" << std::endl;
     208                        WidenMode newWidenMode ( widen1, widen2 );
     209                        Type *common = 0;
     210                        if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
     211                                EqvClass newClass1 = *class1;
     212                                newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
     213                                newClass1.allowWidening = widen1 && widen2;
     214                                if ( common ) {
     215                                        common->get_qualifiers() = Type::Qualifiers();
     216                                        newClass1.type = common;
     217                                } // if
     218                                env.add( std::move(newClass1) );
     219                        } else {
     220                                result = false;
     221                        } // if
     222                } else if ( class1 && class2 ) {
     223                        if ( type1 ) {
     224                                EqvClass newClass1 = *class1;
     225                                newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
     226                                newClass1.allowWidening = widen1;
     227                                env.add( std::move(newClass1) );
     228                        } else {
     229                                EqvClass newClass2 = *class2;
     230                                newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
     231                                newClass2.allowWidening = widen2;
     232                                env.add( std::move(newClass2) );
     233                        } // if
     234                } else if ( class1 ) {
     235                        EqvClass newClass1 = *class1;
     236                        newClass1.vars.insert( var2->get_name() );
     237                        newClass1.allowWidening = widen1;
     238                        env.add( std::move(newClass1) );
     239                } else if ( class2 ) {
     240                        EqvClass newClass2 = *class2;
     241                        newClass2.vars.insert( var1->get_name() );
     242                        newClass2.allowWidening = widen2;
     243                        env.add( std::move(newClass2) );
     244                } else {
     245                        EqvClass newClass;
     246                        newClass.vars.insert( var1->get_name() );
     247                        newClass.vars.insert( var2->get_name() );
     248                        newClass.allowWidening = widen1 && widen2;
     249                        newClass.data = data;
     250                        env.add( newClass );
     251                } // if
     252                return result;
     253        }
     254
    124255        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    125256                OpenVarSet closedVars;
     
    159290
    160291                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    161                         result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     292                        result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    162293                } else if ( isopen1 ) {
    163                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     294                        result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    164295                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    165                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     296                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    166297                } else {
    167298                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
  • src/ResolvExpr/Unify.h

    rb21c77a r97397a26  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 23:09:34 2017
     13// Update Count     : 3
    1414//
    1515
     
    2121#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2222#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    23 #include "WidenMode.h"            // for WidenMode
    2423
    2524class Type;
     
    3029
    3130namespace ResolvExpr {
     31        struct WidenMode {
     32                WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
     33                WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
     34                WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
     35                WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
     36                WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
     37                operator bool() { return widenFirst && widenSecond; }
     38
     39                bool widenFirst : 1, widenSecond : 1;
     40        };
     41
     42        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    3243        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    3344        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    3445        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    35         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    3646
    3747        template< typename Iterator1, typename Iterator2 >
  • src/SymTab/Indexer.cc

    rb21c77a r97397a26  
    106106                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
    107107
    108                 // helpful data structure to organize properties for a type
     108                // helpful data structure
    109109                struct ValueType {
    110                         struct DeclBall { // properties for this particular decl
     110                        struct DeclBall {
    111111                                IdData decl;
    112                                 bool isUserDefinedFunc;
     112                                bool isUserDefinedFunc; // properties for this particular decl
     113                                bool isDefaultCtor;
     114                                bool isDtor;
    113115                                bool isCopyFunc;
    114116                        };
    115117                        // properties for this type
     118                        bool existsUserDefinedFunc = false;    // any user-defined function found
     119                        bool existsUserDefinedCtor = false;    // any user-defined constructor found
     120                        bool existsUserDefinedDtor = false;    // any user-defined destructor found
    116121                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
    117                         BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
     122                        bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found
    118123                        std::list< DeclBall > decls;
    119124
     
    122127                        ValueType & operator+=( IdData data ) {
    123128                                DeclarationWithType * function = data.id;
    124                                 bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
    125                                 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
    126                                 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
     129                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
     130                                bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
     131                                bool isDtor = InitTweak::isDestructor( function );
     132                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
     133                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
     134                                existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
     135                                existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
     136                                existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
    127137                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    128                                 if ( isUserDefinedFunc && ! deleteStmt ) {
    129                                         // any user-defined function can act as an implicit delete statement for generated constructors.
    130                                         // a delete stmt should not act as an implicit delete statement.
    131                                         deleteStmt = data.id;
    132                                 }
     138                                existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor);
    133139                                return *this;
    134140                        }
     
    142148                for ( auto decl : copy ) {
    143149                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
    144                                 std::list< DeclarationWithType * > & params = function->type->parameters;
     150                                std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
    145151                                assert( ! params.empty() );
    146152                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     
    154160
    155161                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
    156                 // the set of ctor/dtor/assign that can be used  by the requester. In particular, if the user defines
    157                 // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor
    158                 // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available.
    159                 // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default
    160                 // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor,
    161                 // then the generated copy constructor is unavailable, and likewise for the assignment operator.
     162                // the set of ctor/dtor/assign that are seen by the requester. In particular, if the user defines
     163                // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
     164                // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
     165                // If the user defines any ctor then the generated default ctor should not be seen (intrinsic default
     166                // ctor must be overridden exactly).
    162167                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    163168                        ValueType & val = pair.second;
    164169                        for ( ValueType::DeclBall ball : val.decls ) {
    165                                 bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
    166                                 bool isCopyFunc = ball.isCopyFunc;
    167                                 bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
    168 
    169                                 // only implicitly delete non-user defined functions that are not intrinsic, and are
    170                                 // not copy functions (assignment or copy constructor). If a  user-defined copy function exists,
    171                                 // do not pass along the non-user-defined copy functions since signatures do not have to match,
    172                                 // and the generated functions will often be cheaper.
    173                                 if ( isNotUserDefinedFunc ) {
    174                                         if ( isCopyFunc ) {
    175                                                 // Skip over non-user-defined copy functions when there is a user-defined copy function.
    176                                                 // Since their signatures do not have to be exact, deleting them is the wrong choice.
    177                                                 if ( existsUserDefinedCopyFunc ) continue;
    178                                         } else {
    179                                                 // delete non-user-defined non-copy functions if applicable.
    180                                                 // deleteStmt will be non-null only if a user-defined function is found.
    181                                                 ball.decl.deleteStmt = val.deleteStmt;
    182                                         }
     170                                bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
     171                                bool isUserDefinedFunc = ball.isUserDefinedFunc;
     172                                bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
     173                                bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
     174                                bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
     175                                if ( noUserDefinedFunc || isUserDefinedFunc || isAcceptableDefaultCtor || isAcceptableCopyFunc || isAcceptableDtor ) {
     176                                        // decl conforms to the rules described above, so it should be seen by the requester
     177                                        out.push_back( ball.decl );
    183178                                }
    184                                 out.push_back( ball.decl );
    185179                        }
    186180                }
     
    477471        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
    478472                // default handling of conflicts is to raise an error
    479                 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
     473                addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr );
    480474        }
    481475
  • src/SymTab/Mangler.cc

    rb21c77a r97397a26  
    171171                                        "w",    // SignedInt128
    172172                                        "Uw",   // UnsignedInt128
    173                                         "x",   // Float80
    174                                         "y",   // Float128
    175173                                };
    176                                 static_assert(
    177                                         sizeof(btLetter)/sizeof(btLetter[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
    178                                         "Each basic type kind should have a corresponding mangler letter"
    179                                 );
    180174
    181175                                printQualifiers( basicType );
    182                                 assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) );
    183176                                mangleName << btLetter[ basicType->get_kind() ];
    184177                        }
     
    225218                                GuardValue( inFunctionType );
    226219                                inFunctionType = true;
    227                                 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
     220                                std::list< Type* > returnTypes = getTypes( functionType->get_returnVals() );
    228221                                acceptAll( returnTypes, *visitor );
    229222                                mangleName << "_";
    230                                 std::list< Type* > paramTypes = getTypes( functionType->parameters );
     223                                std::list< Type* > paramTypes = getTypes( functionType->get_parameters() );
    231224                                acceptAll( paramTypes, *visitor );
    232225                                mangleName << "_";
     
    236229                                printQualifiers( refType );
    237230
    238                                 mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
     231                                mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name();
    239232
    240233                                if ( mangleGenericParams ) {
    241                                         std::list< Expression* >& params = refType->parameters;
     234                                        std::list< Expression* >& params = refType->get_parameters();
    242235                                        if ( ! params.empty() ) {
    243236                                                mangleName << "_";
    244237                                                for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
    245238                                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    246                                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
    247                                                         maybeAccept( paramType->type, *visitor );
     239                                                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str());
     240                                                        maybeAccept( paramType->get_type(), *visitor );
    248241                                                }
    249242                                                mangleName << "_";
  • src/SymTab/Validate.cc

    rb21c77a r97397a26  
    4949#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5050#include "Common/GC.h"                 // for new_static_root, register_static_root
    51 #include "ControlStruct/Mutate.h"      // for ForExprMutator
    5251#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    5352#include "Common/ScopedMap.h"          // for ScopedMap
     
    7877class SwitchStmt;
    7978
     79
    8080#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
    8181
     
    275275                Concurrency::applyKeywords( translationUnit );
    276276                acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    277                 ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
    278277                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
    279278                Concurrency::implementMutexFuncs( translationUnit );
  • src/SynTree/BasicType.cc

    rb21c77a r97397a26  
    5555          case DoubleImaginary:
    5656          case LongDoubleImaginary:
    57           case Float80:
    58           case Float128:
    5957                return false;
    6058          case NUMBER_OF_BASIC_TYPES:
  • src/SynTree/Declaration.cc

    rb21c77a r97397a26  
    9292}
    9393
    94 
    9594// Local Variables: //
    9695// tab-width: 4 //
  • src/SynTree/Declaration.h

    rb21c77a r97397a26  
    8383        Expression *asmName;
    8484        std::list< Attribute * > attributes;
    85         bool isDeleted = false;
    8685
    8786        DeclarationWithType( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage, const std::list< Attribute * > & attributes, Type::FuncSpecifiers fs );
  • src/SynTree/Expression.cc

    rb21c77a r97397a26  
    640640
    641641
    642 DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
    643         assert( expr->result );
    644         result = expr->result->clone();
    645 }
    646 DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
    647 
    648 void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
    649         os << "Default Argument Expression" << std::endl << indent+1;
    650         expr->print( os, indent+1 );
    651 }
    652 
    653 GenericExpr::Association::Association( Type * type, Expression * expr ) : type( type ), expr( expr ), isDefault( false ) {}
    654 GenericExpr::Association::Association( Expression * expr ) : type( nullptr ), expr( expr ), isDefault( true ) {}
    655 GenericExpr::Association::Association( const Association & other ) : type( maybeClone( other.type ) ), expr( maybeClone( other.expr ) ), isDefault( other.isDefault ) {}
    656 
    657 GenericExpr::GenericExpr( Expression * control, const std::list<Association> & assoc ) : Expression(), control( control ), associations( assoc ) {}
    658 GenericExpr::GenericExpr( const GenericExpr & other ) : Expression(other), control( maybeClone( other.control ) ), associations( other.associations ) {}
    659 GenericExpr::~GenericExpr() {}
    660 
    661 void GenericExpr::print( std::ostream & os, Indenter indent ) const {
    662         os << "C11 _Generic Expression" << std::endl << indent+1;
    663         control->print( os, indent+1 );
    664         os << std::endl << indent+1 << "... with associations: " << std::endl;
    665         for ( const Association & assoc : associations ) {
    666                 os << indent+1;
    667                 if (assoc.isDefault) {
    668                         os << "... default: ";
    669                         assoc.expr->print( os, indent+1 );
    670                 } else {
    671                         os << "... type: ";
    672                         assoc.type->print( os, indent+1 );
    673                         os << std::endl << indent+1 << "... expression: ";
    674                         assoc.expr->print( os, indent+1 );
    675                         os << std::endl;
    676                 }
    677                 os << std::endl;
    678         }
    679 }
    680 
    681642// Local Variables: //
    682643// tab-width: 4 //
  • src/SynTree/Expression.h

    rb21c77a r97397a26  
    833833};
    834834
    835 /// expression wrapping the use of a default argument - should never make it past the resolver.
    836 class DefaultArgExpr : public Expression {
    837 public:
    838         Expression * expr;
    839 
    840         DefaultArgExpr( Expression * expr );
    841         DefaultArgExpr( const DefaultArgExpr & other );
    842 
    843         virtual DefaultArgExpr * clone() const { return new DefaultArgExpr( * this ); }
    844         virtual void accept( Visitor & v ) { v.visit( this ); }
    845         virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    846         virtual void print( std::ostream & os, Indenter indent = {} ) const;
    847 };
    848 
    849 /// C11 _Generic expression
    850 class GenericExpr : public Expression {
    851 public:
    852         struct Association {
    853                 Type * type = nullptr;
    854                 Expression * expr = nullptr;
    855                 bool isDefault = false;
    856 
    857                 Association( Type * type, Expression * expr );
    858                 Association( Expression * expr );
    859                 Association( const Association & other );
    860                 Association & operator=( const Association & other ) = delete; // at the moment this isn't used, and I don't want to implement it
    861         };
    862 
    863         Expression * control;
    864         std::list<Association> associations;
    865 
    866         GenericExpr( Expression * control, const std::list<Association> & assoc );
    867         GenericExpr( const GenericExpr & other );
    868         ~GenericExpr();
    869 
    870         virtual GenericExpr * clone() const { return new GenericExpr( * this ); }
    871         virtual void accept( Visitor & v ) { v.visit( this ); }
    872         virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    873         virtual void print( std::ostream & os, Indenter indent = {} ) const;
    874 };
    875 
    876835// Local Variables: //
    877836// tab-width: 4 //
  • src/SynTree/Mutator.h

    rb21c77a r97397a26  
    9393        virtual Expression * mutate( InitExpr  * initExpr ) = 0;
    9494        virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
    95         virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
    96         virtual Expression * mutate( GenericExpr * genExpr ) = 0;
    9795
    9896        virtual Type * mutate( VoidType * basicType ) = 0;
  • src/SynTree/ReferenceToType.cc

    rb21c77a r97397a26  
    4646
    4747namespace {
    48         void doLookup( const std::list< Declaration * > & members, const std::string & name, std::list< Declaration* > & foundDecls ) {
    49                 for ( Declaration * decl : members ) {
    50                         if ( decl->name == name ) {
    51                                 foundDecls.push_back( decl );
     48        void doLookup( const std::list< Declaration* > &members, const std::string &name, std::list< Declaration* > &foundDecls ) {
     49                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
     50                        if ( (*i)->get_name() == name ) {
     51                                foundDecls.push_back( *i );
    5252                        } // if
    5353                } // for
     
    5656
    5757StructInstType::StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct, const std::list< Attribute * > & attributes ) :
    58                 Parent( tq, baseStruct->name, attributes ), baseStruct( baseStruct ) {}
     58                Parent( tq, baseStruct->get_name(), attributes ), baseStruct( baseStruct ) {}
    5959
    6060std::string StructInstType::typeString() const { return "struct"; }
     
    8080void StructInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
    8181        assert( baseStruct );
    82         doLookup( baseStruct->members, name, foundDecls );
     82        doLookup( baseStruct->get_members(), name, foundDecls );
    8383}
    8484
     
    9999
    100100UnionInstType::UnionInstType( const Type::Qualifiers & tq, UnionDecl * baseUnion, const std::list< Attribute * > & attributes ) :
    101                 Parent( tq, baseUnion->name, attributes ), baseUnion( baseUnion ) {}
     101                Parent( tq, baseUnion->get_name(), attributes ), baseUnion( baseUnion ) {}
    102102
    103103std::string UnionInstType::typeString() const { return "union"; }
     
    123123void UnionInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
    124124        assert( baseUnion );
    125         doLookup( baseUnion->members, name, foundDecls );
     125        doLookup( baseUnion->get_members(), name, foundDecls );
    126126}
    127127
  • src/SynTree/Statement.cc

    rb21c77a r97397a26  
    208208}
    209209
    210 WhileStmt::WhileStmt( Expression *condition, Statement *body, std::list< Statement * > & initialization, bool isDoWhile ):
    211         Statement(), condition( condition), body( body), initialization( initialization ), isDoWhile( isDoWhile) {
     210WhileStmt::WhileStmt( Expression *condition, Statement *body, bool isDoWhile ):
     211        Statement(), condition( condition), body( body), isDoWhile( isDoWhile) {
    212212}
    213213
  • src/SynTree/Statement.h

    rb21c77a r97397a26  
    213213        Expression *condition;
    214214        Statement *body;
    215         std::list<Statement *> initialization;
    216215        bool isDoWhile;
    217216
    218217        WhileStmt( Expression *condition,
    219                Statement *body, std::list<Statement *> & initialization, bool isDoWhile = false );
     218               Statement *body, bool isDoWhile = false );
    220219        WhileStmt( const WhileStmt &other );
    221220
  • src/SynTree/SynTree.h

    rb21c77a r97397a26  
    101101class InitExpr;
    102102class DeletedExpr;
    103 class DefaultArgExpr;
    104 class GenericExpr;
    105103
    106104class Type;
  • src/SynTree/Type.cc

    rb21c77a r97397a26  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 22 10:17:19 2018
    13 // Update Count     : 39
     12// Last Modified On : Mon Sep 25 15:16:32 2017
     13// Update Count     : 38
    1414//
    1515#include "Type.h"
     
    2424using namespace std;
    2525
    26 const char *BasicType::typeNames[] = {
     26const char *BasicType::typeNames[BasicType::NUMBER_OF_BASIC_TYPES] = {
    2727        "_Bool",
    2828        "char",
     
    4848        "__int128",
    4949        "unsigned __int128",
    50         "__float80",
    51         "__float128"
    5250};
    53 static_assert(
    54         sizeof(BasicType::typeNames)/sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
    55         "Each basic type name should have a corresponding kind enum value"
    56 );
    5751
    5852Type::Type( const Qualifiers &tq, const std::list< Attribute * > & attributes ) : tq( tq ), attributes( attributes ) {}
     
    6458
    6559// These must remain in the same order as the corresponding bit fields.
    66 const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
     60const char * Type::FuncSpecifiersNames[] = { "inline", "fortran", "_Noreturn" };
    6761const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
    6862const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
  • src/SynTree/Type.h

    rb21c77a r97397a26  
    230230                SignedInt128,
    231231                UnsignedInt128,
    232                 Float80,
    233                 Float128,
    234232                NUMBER_OF_BASIC_TYPES
    235233        } kind;
  • src/SynTree/Visitor.h

    rb21c77a r97397a26  
    9595        virtual void visit( InitExpr *  initExpr ) = 0;
    9696        virtual void visit( DeletedExpr * delExpr ) = 0;
    97         virtual void visit( DefaultArgExpr * argExpr ) = 0;
    98         virtual void visit( GenericExpr * genExpr ) = 0;
    9997
    10098        virtual void visit( VoidType * basicType ) = 0;
  • src/benchmark/Makefile.am

    rb21c77a r97397a26  
    9292
    9393## =========================================================================================================
    94 loop$(EXEEXT):
    95         @@BACKEND_CC@ loop.c      -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    96 
    97 function$(EXEEXT):
    98         @@BACKEND_CC@ function.c  -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    99 
    100 fetch_add$(EXEEXT):
    101         @@BACKEND_CC@ fetch_add.c -DBENCH_N=500000000  -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    102 
    103 ## =========================================================================================================
    10494ctxswitch$(EXEEXT): \
    105         loop.run                                \
    106         function.run                    \
    107         fetch_add.run                   \
    10895        ctxswitch-pthread.run           \
    10996        ctxswitch-cfa_coroutine.run     \
    11097        ctxswitch-cfa_thread.run        \
    111         ctxswitch-cfa_thread2.run       \
    11298        ctxswitch-upp_coroutine.run     \
    11399        ctxswitch-upp_thread.run        \
    114         -ctxswitch-kos_fibre.run        \
    115         -ctxswitch-kos_fibre2.run       \
    116100        ctxswitch-goroutine.run         \
    117101        ctxswitch-java_thread.run
    118102
     103ctxswitch-cfa_coroutine$(EXEEXT):
     104        @${CC}        ctxswitch/cfa_cor.c   -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     105
     106ctxswitch-cfa_thread$(EXEEXT):
     107        @${CC}        ctxswitch/cfa_thrd.c  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     108
     109ctxswitch-upp_coroutine$(EXEEXT):
     110        @u++          ctxswitch/upp_cor.cc  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     111
     112ctxswitch-upp_thread$(EXEEXT):
     113        @u++          ctxswitch/upp_thrd.cc -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     114
    119115ctxswitch-pthread$(EXEEXT):
    120         @@BACKEND_CC@ ctxswitch/pthreads.c     -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    121 
    122 ctxswitch-cfa_coroutine$(EXEEXT):
    123         @${CC}        ctxswitch/cfa_cor.c      -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    124 
    125 ctxswitch-cfa_thread$(EXEEXT):
    126         @${CC}        ctxswitch/cfa_thrd.c     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    127 
    128 ctxswitch-cfa_thread2$(EXEEXT):
    129         @${CC}        ctxswitch/cfa_thrd2.c    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    130 
    131 ctxswitch-upp_coroutine$(EXEEXT):
    132         @u++          ctxswitch/upp_cor.cc     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    133 
    134 ctxswitch-upp_thread$(EXEEXT):
    135         @u++          ctxswitch/upp_thrd.cc    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    136 
    137 ctxswitch-kos_fibre$(EXEEXT):
    138         @${CXX}       ctxswitch/kos_fibre.cpp  -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
    139 
    140 ctxswitch-kos_fibre2$(EXEEXT):
    141         @${CXX}       ctxswitch/kos_fibre2.cpp -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
     116        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    142117
    143118ctxswitch-goroutine$(EXEEXT):
     
    152127## =========================================================================================================
    153128mutex$(EXEEXT) :\
    154         loop.run                        \
    155         function.run            \
    156         fetch_add.run           \
     129        mutex-function.run      \
     130        mutex-fetch_add.run     \
    157131        mutex-pthread_lock.run  \
    158132        mutex-upp.run           \
     
    161135        mutex-cfa4.run          \
    162136        mutex-java_thread.run
     137
     138mutex-function$(EXEEXT):
     139        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     140
     141mutex-fetch_add$(EXEEXT):
     142        @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    163143
    164144mutex-pthread_lock$(EXEEXT):
     
    297277
    298278compile-io$(EXEEXT):
    299         @${CC} -quiet -fsyntax-only -w ../tests/io1.c                           @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     279        @${CC} -quiet -fsyntax-only -w ../tests/io.c                                    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    300280
    301281compile-monitor$(EXEEXT):
    302         @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     282        @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c            @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    303283
    304284compile-operators$(EXEEXT):
     
    309289
    310290compile-typeof$(EXEEXT):
    311         @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                        @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    312 
     291        @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                                @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     292
  • src/benchmark/Makefile.in

    rb21c77a r97397a26  
    505505        @echo "}"
    506506
    507 loop$(EXEEXT):
    508         @@BACKEND_CC@ loop.c      -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    509 
    510 function$(EXEEXT):
    511         @@BACKEND_CC@ function.c  -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    512 
    513 fetch_add$(EXEEXT):
    514         @@BACKEND_CC@ fetch_add.c -DBENCH_N=500000000  -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    515 
    516507ctxswitch$(EXEEXT): \
    517         loop.run                                \
    518         function.run                    \
    519         fetch_add.run                   \
    520508        ctxswitch-pthread.run           \
    521509        ctxswitch-cfa_coroutine.run     \
    522510        ctxswitch-cfa_thread.run        \
    523         ctxswitch-cfa_thread2.run       \
    524511        ctxswitch-upp_coroutine.run     \
    525512        ctxswitch-upp_thread.run        \
    526         -ctxswitch-kos_fibre.run        \
    527         -ctxswitch-kos_fibre2.run       \
    528513        ctxswitch-goroutine.run         \
    529514        ctxswitch-java_thread.run
    530515
     516ctxswitch-cfa_coroutine$(EXEEXT):
     517        @${CC}        ctxswitch/cfa_cor.c   -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     518
     519ctxswitch-cfa_thread$(EXEEXT):
     520        @${CC}        ctxswitch/cfa_thrd.c  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     521
     522ctxswitch-upp_coroutine$(EXEEXT):
     523        @u++          ctxswitch/upp_cor.cc  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     524
     525ctxswitch-upp_thread$(EXEEXT):
     526        @u++          ctxswitch/upp_thrd.cc -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     527
    531528ctxswitch-pthread$(EXEEXT):
    532         @@BACKEND_CC@ ctxswitch/pthreads.c     -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    533 
    534 ctxswitch-cfa_coroutine$(EXEEXT):
    535         @${CC}        ctxswitch/cfa_cor.c      -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    536 
    537 ctxswitch-cfa_thread$(EXEEXT):
    538         @${CC}        ctxswitch/cfa_thrd.c     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    539 
    540 ctxswitch-cfa_thread2$(EXEEXT):
    541         @${CC}        ctxswitch/cfa_thrd2.c    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    542 
    543 ctxswitch-upp_coroutine$(EXEEXT):
    544         @u++          ctxswitch/upp_cor.cc     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    545 
    546 ctxswitch-upp_thread$(EXEEXT):
    547         @u++          ctxswitch/upp_thrd.cc    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    548 
    549 ctxswitch-kos_fibre$(EXEEXT):
    550         @${CXX}       ctxswitch/kos_fibre.cpp  -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
    551 
    552 ctxswitch-kos_fibre2$(EXEEXT):
    553         @${CXX}       ctxswitch/kos_fibre2.cpp -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
     529        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    554530
    555531ctxswitch-goroutine$(EXEEXT):
     
    563539
    564540mutex$(EXEEXT) :\
    565         loop.run                        \
    566         function.run            \
    567         fetch_add.run           \
     541        mutex-function.run      \
     542        mutex-fetch_add.run     \
    568543        mutex-pthread_lock.run  \
    569544        mutex-upp.run           \
     
    572547        mutex-cfa4.run          \
    573548        mutex-java_thread.run
     549
     550mutex-function$(EXEEXT):
     551        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     552
     553mutex-fetch_add$(EXEEXT):
     554        @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    574555
    575556mutex-pthread_lock$(EXEEXT):
     
    701682
    702683compile-io$(EXEEXT):
    703         @${CC} -quiet -fsyntax-only -w ../tests/io1.c                           @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     684        @${CC} -quiet -fsyntax-only -w ../tests/io.c                                    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    704685
    705686compile-monitor$(EXEEXT):
    706         @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     687        @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c            @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    707688
    708689compile-operators$(EXEEXT):
     
    713694
    714695compile-typeof$(EXEEXT):
    715         @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                        @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     696        @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                                @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    716697
    717698# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • src/libcfa/Makefile.am

    rb21c77a r97397a26  
    5151# not all platforms support concurrency, add option do disable it
    5252if BUILD_CONCURRENCY
    53 headers += concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor concurrency/mutex
     53headers += concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor
    5454endif
    5555
  • src/libcfa/Makefile.in

    rb21c77a r97397a26  
    9797
    9898# not all platforms support concurrency, add option do disable it
    99 @BUILD_CONCURRENCY_TRUE@am__append_3 = concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor concurrency/mutex
     99@BUILD_CONCURRENCY_TRUE@am__append_3 = concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor
    100100
    101101# not all platforms support concurrency, add option do disable it
     
    153153        containers/pair.c containers/result.c containers/vector.c \
    154154        concurrency/coroutine.c concurrency/thread.c \
    155         concurrency/kernel.c concurrency/monitor.c concurrency/mutex.c \
    156         assert.c exception.c virtual.c \
    157         concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
    158         concurrency/invoke.c concurrency/preemption.c
     155        concurrency/kernel.c concurrency/monitor.c assert.c \
     156        exception.c virtual.c concurrency/CtxSwitch-@MACHINE_TYPE@.S \
     157        concurrency/alarm.c concurrency/invoke.c \
     158        concurrency/preemption.c
    159159am__dirstamp = $(am__leading_dot)dirstamp
    160160@BUILD_CONCURRENCY_TRUE@am__objects_1 = concurrency/libcfa_d_a-coroutine.$(OBJEXT) \
    161161@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-thread.$(OBJEXT) \
    162162@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-kernel.$(OBJEXT) \
    163 @BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-monitor.$(OBJEXT) \
    164 @BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-mutex.$(OBJEXT)
     163@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-monitor.$(OBJEXT)
    165164am__objects_2 = libcfa_d_a-fstream.$(OBJEXT) \
    166165        libcfa_d_a-iostream.$(OBJEXT) libcfa_d_a-iterator.$(OBJEXT) \
     
    189188        containers/result.c containers/vector.c \
    190189        concurrency/coroutine.c concurrency/thread.c \
    191         concurrency/kernel.c concurrency/monitor.c concurrency/mutex.c \
    192         assert.c exception.c virtual.c \
    193         concurrency/CtxSwitch-@MACHINE_TYPE@.S concurrency/alarm.c \
    194         concurrency/invoke.c concurrency/preemption.c
     190        concurrency/kernel.c concurrency/monitor.c assert.c \
     191        exception.c virtual.c concurrency/CtxSwitch-@MACHINE_TYPE@.S \
     192        concurrency/alarm.c concurrency/invoke.c \
     193        concurrency/preemption.c
    195194@BUILD_CONCURRENCY_TRUE@am__objects_5 = concurrency/libcfa_a-coroutine.$(OBJEXT) \
    196195@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-thread.$(OBJEXT) \
    197196@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-kernel.$(OBJEXT) \
    198 @BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-monitor.$(OBJEXT) \
    199 @BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-mutex.$(OBJEXT)
     197@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-monitor.$(OBJEXT)
    200198am__objects_6 = libcfa_a-fstream.$(OBJEXT) libcfa_a-iostream.$(OBJEXT) \
    201199        libcfa_a-iterator.$(OBJEXT) libcfa_a-limits.$(OBJEXT) \
     
    266264        containers/result containers/vector concurrency/coroutine \
    267265        concurrency/thread concurrency/kernel concurrency/monitor \
    268         concurrency/mutex ${shell find stdhdr -type f -printf "%p "} \
    269         math gmp time_t.h clock bits/align.h bits/containers.h \
    270         bits/defs.h bits/debug.h bits/locks.h concurrency/invoke.h
     266        ${shell find stdhdr -type f -printf "%p "} math gmp time_t.h \
     267        clock bits/align.h bits/containers.h bits/defs.h bits/debug.h \
     268        bits/locks.h concurrency/invoke.h
    271269HEADERS = $(nobase_cfa_include_HEADERS)
    272270am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
     
    550548concurrency/libcfa_d_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
    551549        concurrency/$(DEPDIR)/$(am__dirstamp)
    552 concurrency/libcfa_d_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
    553         concurrency/$(DEPDIR)/$(am__dirstamp)
    554550concurrency/CtxSwitch-@MACHINE_TYPE@.$(OBJEXT):  \
    555551        concurrency/$(am__dirstamp) \
     
    584580        concurrency/$(DEPDIR)/$(am__dirstamp)
    585581concurrency/libcfa_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
    586         concurrency/$(DEPDIR)/$(am__dirstamp)
    587 concurrency/libcfa_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
    588582        concurrency/$(DEPDIR)/$(am__dirstamp)
    589583concurrency/libcfa_a-alarm.$(OBJEXT): concurrency/$(am__dirstamp) \
     
    641635@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-kernel.Po@am__quote@
    642636@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-monitor.Po@am__quote@
    643 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-mutex.Po@am__quote@
    644637@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-preemption.Po@am__quote@
    645638@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-thread.Po@am__quote@
     
    649642@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-kernel.Po@am__quote@
    650643@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-monitor.Po@am__quote@
    651 @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po@am__quote@
    652644@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-preemption.Po@am__quote@
    653645@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-thread.Po@am__quote@
     
    938930@am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
    939931
    940 concurrency/libcfa_d_a-mutex.o: concurrency/mutex.c
    941 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_d_a-mutex.o -MD -MP -MF concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo -c -o concurrency/libcfa_d_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
    942 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po
    943 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_d_a-mutex.o' libtool=no @AMDEPBACKSLASH@
    944 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    945 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
    946 
    947 concurrency/libcfa_d_a-mutex.obj: concurrency/mutex.c
    948 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_d_a-mutex.obj -MD -MP -MF concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo -c -o concurrency/libcfa_d_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
    949 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_d_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_d_a-mutex.Po
    950 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_d_a-mutex.obj' libtool=no @AMDEPBACKSLASH@
    951 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    952 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_d_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
    953 
    954932libcfa_d_a-assert.o: assert.c
    955933@am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_d_a_CFLAGS) $(CFLAGS) -MT libcfa_d_a-assert.o -MD -MP -MF $(DEPDIR)/libcfa_d_a-assert.Tpo -c -o libcfa_d_a-assert.o `test -f 'assert.c' || echo '$(srcdir)/'`assert.c
     
    12591237@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    12601238@am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-monitor.obj `if test -f 'concurrency/monitor.c'; then $(CYGPATH_W) 'concurrency/monitor.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/monitor.c'; fi`
    1261 
    1262 concurrency/libcfa_a-mutex.o: concurrency/mutex.c
    1263 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_a-mutex.o -MD -MP -MF concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo -c -o concurrency/libcfa_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
    1264 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_a-mutex.Po
    1265 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_a-mutex.o' libtool=no @AMDEPBACKSLASH@
    1266 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1267 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-mutex.o `test -f 'concurrency/mutex.c' || echo '$(srcdir)/'`concurrency/mutex.c
    1268 
    1269 concurrency/libcfa_a-mutex.obj: concurrency/mutex.c
    1270 @am__fastdepCC_TRUE@    $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -MT concurrency/libcfa_a-mutex.obj -MD -MP -MF concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo -c -o concurrency/libcfa_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
    1271 @am__fastdepCC_TRUE@    $(AM_V_at)$(am__mv) concurrency/$(DEPDIR)/libcfa_a-mutex.Tpo concurrency/$(DEPDIR)/libcfa_a-mutex.Po
    1272 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='concurrency/mutex.c' object='concurrency/libcfa_a-mutex.obj' libtool=no @AMDEPBACKSLASH@
    1273 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1274 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfa_a_CFLAGS) $(CFLAGS) -c -o concurrency/libcfa_a-mutex.obj `if test -f 'concurrency/mutex.c'; then $(CYGPATH_W) 'concurrency/mutex.c'; else $(CYGPATH_W) '$(srcdir)/concurrency/mutex.c'; fi`
    12751239
    12761240libcfa_a-assert.o: assert.c
  • src/libcfa/bits/containers.h

    rb21c77a r97397a26  
    183183                verify( *tail == NULL );
    184184                return val;
    185         }
    186 
    187         forall(dtype T | is_node(T))
    188         static inline bool ?!=?( __queue(T) & this, zero_t zero ) {
    189                 return this.head != 0;
    190185        }
    191186#endif
     
    266261                __get( node ).prev = NULL;
    267262        }
    268 
    269         forall(dtype T | sized(T))
    270         static inline bool ?!=?( __dllist(T) & this, zero_t zero ) {
    271                 return this.head != 0;
    272         }
    273263        #undef next
    274264        #undef prev
  • src/libcfa/bits/locks.h

    rb21c77a r97397a26  
    1818#include "bits/debug.h"
    1919#include "bits/defs.h"
    20 #include <assert.h>
    21 
    22 #ifdef __cforall
    23         extern "C" {
    24                 #include <pthread.h>
    25         }
    26 #endif
    2720
    2821// pause to prevent excess processor bus usage
     
    119112                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    120113        }
    121 
    122 
    123         #ifdef __CFA_WITH_VERIFY__
    124                 extern bool __cfaabi_dbg_in_kernel();
    125         #endif
    126 
    127         struct __bin_sem_t {
    128                 bool                    signaled;
    129                 pthread_mutex_t         lock;
    130                 pthread_cond_t          cond;
    131         };
    132 
    133         static inline void ?{}(__bin_sem_t & this) with( this ) {
    134                 signaled = false;
    135                 pthread_mutex_init(&lock, NULL);
    136                 pthread_cond_init (&cond, NULL);
    137         }
    138 
    139         static inline void ^?{}(__bin_sem_t & this) with( this ) {
    140                 pthread_mutex_destroy(&lock);
    141                 pthread_cond_destroy (&cond);
    142         }
    143 
    144         static inline void wait(__bin_sem_t & this) with( this ) {
    145                 verify(__cfaabi_dbg_in_kernel());
    146                 pthread_mutex_lock(&lock);
    147                         if(!signaled) {   // this must be a loop, not if!
    148                                 pthread_cond_wait(&cond, &lock);
    149                         }
    150                         signaled = false;
    151                 pthread_mutex_unlock(&lock);
    152         }
    153 
    154         static inline void post(__bin_sem_t & this) with( this ) {
    155                 verify(__cfaabi_dbg_in_kernel());
    156 
    157                 pthread_mutex_lock(&lock);
    158                         bool needs_signal = !signaled;
    159                         signaled = true;
    160                 pthread_mutex_unlock(&lock);
    161 
    162                 if (needs_signal)
    163                         pthread_cond_signal(&cond);
    164         }
    165114#endif
  • src/libcfa/concurrency/invoke.h

    rb21c77a r97397a26  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 19 08:23:21 2018
    13 // Update Count     : 31
     12// Last Modified On : Fri Mar 30 22:33:59 2018
     13// Update Count     : 30
    1414//
    1515
     
    1818#include "bits/locks.h"
    1919
     20#define TL_GET( member ) kernelTLS.member
     21#define TL_SET( member, value ) kernelTLS.member = value;
     22
    2023#ifdef __cforall
    2124extern "C" {
     
    2528#ifndef _INVOKE_H_
    2629#define _INVOKE_H_
    27 
    28 #ifdef __ARM_ARCH
    29         // function prototypes are only really used by these macros on ARM
    30         void disable_global_interrupts();
    31         void enable_global_interrupts();
    32 
    33         #define TL_GET( member ) ( { __typeof__( kernelTLS.member ) target; \
    34                 disable_global_interrupts(); \
    35                 target = kernelTLS.member; \
    36                 enable_global_interrupts(); \
    37                 target; } )
    38         #define TL_SET( member, value ) disable_global_interrupts(); \
    39                 kernelTLS.member = value; \
    40                 enable_global_interrupts();
    41 #else
    42         #define TL_GET( member ) kernelTLS.member
    43         #define TL_SET( member, value ) kernelTLS.member = value;
    44 #endif
    4530
    4631        #ifdef __cforall
  • src/libcfa/concurrency/kernel

    rb21c77a r97397a26  
    2323extern "C" {
    2424#include <pthread.h>
    25 #include <semaphore.h>
    2625}
    2726
     
    4443extern struct cluster * mainCluster;
    4544
    46 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
    47 
    48 typedef void (*__finish_callback_fptr_t)(void);
     45enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };
    4946
    5047//TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
    5148struct FinishAction {
    5249        FinishOpCode action_code;
    53         /*
    54         // Union of possible actions
    55         union {
    56                 // Option 1 : locks and threads
    57                 struct {
    58                         // 1 thread or N thread
    59                         union {
    60                                 thread_desc * thrd;
    61                                 struct {
    62                                         thread_desc ** thrds;
    63                                         unsigned short thrd_count;
    64                                 };
    65                         };
    66                         // 1 lock or N lock
    67                         union {
    68                                 __spinlock_t * lock;
    69                                 struct {
    70                                         __spinlock_t ** locks;
    71                                         unsigned short lock_count;
    72                                 };
    73                         };
    74                 };
    75                 // Option 2 : action pointer
    76                 __finish_callback_fptr_t callback;
    77         };
    78         /*/
    7950        thread_desc * thrd;
    80         thread_desc ** thrds;
    81         unsigned short thrd_count;
    8251        __spinlock_t * lock;
    8352        __spinlock_t ** locks;
    8453        unsigned short lock_count;
    85         __finish_callback_fptr_t callback;
    86         //*/
     54        thread_desc ** thrds;
     55        unsigned short thrd_count;
    8756};
    8857static inline void ?{}(FinishAction & this) {
     
    11382        pthread_t kernel_thread;
    11483
     84        // Termination
     85        // Set to true to notify the processor should terminate
     86        volatile bool do_terminate;
     87
     88        // Termination synchronisation
     89        semaphore terminated;
     90
    11591        // RunThread data
    11692        // Action to do after a thread is ran
     
    125101
    126102        // Idle lock
    127         __bin_sem_t idleLock;
    128 
    129         // Termination
    130         // Set to true to notify the processor should terminate
    131         volatile bool do_terminate;
    132 
    133         // Termination synchronisation
    134         semaphore terminated;
    135103
    136104        // Link lists fields
    137         struct __dbg_node_proc {
     105        struct {
    138106                struct processor * next;
    139107                struct processor * prev;
     
    182150
    183151        // Link lists fields
    184         struct __dbg_node_cltr {
     152        struct {
    185153                cluster * next;
    186154                cluster * prev;
  • src/libcfa/concurrency/kernel.c

    rb21c77a r97397a26  
    1616//C Includes
    1717#include <stddef.h>
    18 #include <errno.h>
    19 #include <string.h>
    2018extern "C" {
    2119#include <stdio.h>
     
    5149thread_desc * mainThread;
    5250
    53 extern "C" {
    54 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    55 }
     51struct { __dllist_t(cluster    ) list; __spinlock_t lock; } global_clusters;
    5652
    5753//-----------------------------------------------------------------------------
     
    147143        runner.proc = &this;
    148144
    149         idleLock{};
    150 
    151145        start( &this );
    152146}
    153147
    154148void ^?{}(processor & this) with( this ){
    155         if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
     149        if( ! do_terminate ) {
    156150                __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
    157 
    158                 __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
    159                 wake( &this );
    160 
     151                terminate(&this);
     152                verify(this.do_terminate);
     153                verify( kernelTLS.this_processor != &this);
    161154                P( terminated );
    162155                verify( kernelTLS.this_processor != &this);
    163         }
    164 
    165         pthread_join( kernel_thread, NULL );
     156                pthread_join( kernel_thread, NULL );
     157        }
    166158}
    167159
     
    202194
    203195                thread_desc * readyThread = NULL;
    204                 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ )
     196                for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
    205197                {
    206198                        readyThread = nextThread( this->cltr );
     
    221213                        else
    222214                        {
    223                                 // spin(this, &spin_count);
    224                                 halt(this);
     215                                spin(this, &spin_count);
    225216                        }
    226217                }
     
    266257// its final actions must be executed from the kernel
    267258void finishRunning(processor * this) with( this->finish ) {
    268         verify( ! kernelTLS.preemption_state.enabled );
    269         choose( action_code ) {
    270         case No_Action:
    271                 break;
    272         case Release:
     259        if( action_code == Release ) {
     260                verify( ! kernelTLS.preemption_state.enabled );
    273261                unlock( *lock );
    274         case Schedule:
     262        }
     263        else if( action_code == Schedule ) {
    275264                ScheduleThread( thrd );
    276         case Release_Schedule:
     265        }
     266        else if( action_code == Release_Schedule ) {
     267                verify( ! kernelTLS.preemption_state.enabled );
    277268                unlock( *lock );
    278269                ScheduleThread( thrd );
    279         case Release_Multi:
     270        }
     271        else if( action_code == Release_Multi ) {
     272                verify( ! kernelTLS.preemption_state.enabled );
    280273                for(int i = 0; i < lock_count; i++) {
    281274                        unlock( *locks[i] );
    282275                }
    283         case Release_Multi_Schedule:
     276        }
     277        else if( action_code == Release_Multi_Schedule ) {
    284278                for(int i = 0; i < lock_count; i++) {
    285279                        unlock( *locks[i] );
     
    288282                        ScheduleThread( thrds[i] );
    289283                }
    290         case Callback:
    291                 callback();
    292         default:
    293                 abort("KERNEL ERROR: Unexpected action to run after thread");
    294         }
     284        }
     285        else {
     286                assert(action_code == No_Action);
     287        }
     288}
     289
     290// Handles spinning logic
     291// TODO : find some strategy to put cores to sleep after some time
     292void spin(processor * this, unsigned int * spin_count) {
     293        (*spin_count)++;
    295294}
    296295
     
    397396        with( *thrd->curr_cluster ) {
    398397                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
    399                 bool was_empty = !(ready_queue != 0);
    400398                append( ready_queue, thrd );
    401399                unlock( ready_queue_lock );
    402 
    403                 if(was_empty) {
    404                         lock      (proc_list_lock __cfaabi_dbg_ctx2);
    405                         if(idles) {
    406                                 wake_fast(idles.head);
    407                         }
    408                         unlock    (proc_list_lock);
    409                 }
    410                 else if( struct processor * idle = idles.head ) {
    411                         wake_fast(idle);
    412                 }
    413 
    414400        }
    415401
     
    511497}
    512498
    513 void BlockInternal(__finish_callback_fptr_t callback) {
    514         disable_interrupts();
    515         with( *kernelTLS.this_processor ) {
    516                 finish.action_code = Callback;
    517                 finish.callback    = callback;
    518         }
    519 
    520         verify( ! kernelTLS.preemption_state.enabled );
    521         returnToKernel();
    522         verify( ! kernelTLS.preemption_state.enabled );
    523 
    524         enable_interrupts( __cfaabi_dbg_ctx );
    525 }
    526 
    527499// KERNEL ONLY
    528500void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
     
    546518        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    547519
    548         __cfa_dbg_global_clusters.list{ __get };
    549         __cfa_dbg_global_clusters.lock{};
     520        global_clusters.list{ __get };
     521        global_clusters.lock{};
    550522
    551523        // Initialize the main cluster
     
    628600        // When its coroutine terminates, it return control to the mainThread
    629601        // which is currently here
    630         __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
     602        mainProcessor->do_terminate = true;
    631603        returnToKernel();
    632         mainThread->self_cor.state = Halted;
    633604
    634605        // THE SYSTEM IS NOW COMPLETELY STOPPED
     
    646617        ^(mainThread){};
    647618
    648         ^(__cfa_dbg_global_clusters.list){};
    649         ^(__cfa_dbg_global_clusters.lock){};
     619        ^(global_clusters.list){};
     620        ^(global_clusters.lock){};
    650621
    651622        __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n");
     
    656627//=============================================================================================
    657628
    658 void halt(processor * this) with( *this ) {
    659         // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    660 
    661         with( *cltr ) {
    662                 lock      (proc_list_lock __cfaabi_dbg_ctx2);
    663                 remove    (procs, *this);
    664                 push_front(idles, *this);
    665                 unlock    (proc_list_lock);
    666         }
    667 
    668         __cfaabi_dbg_print_safe("Kernel : Processor %p ready to sleep\n", this);
    669 
    670         wait( idleLock );
    671 
    672         __cfaabi_dbg_print_safe("Kernel : Processor %p woke up and ready to run\n", this);
    673 
    674         with( *cltr ) {
    675                 lock      (proc_list_lock __cfaabi_dbg_ctx2);
    676                 remove    (idles, *this);
    677                 push_front(procs, *this);
    678                 unlock    (proc_list_lock);
    679         }
    680 }
     629// void halt(processor * this) with( this ) {
     630//      pthread_mutex_lock( &idle.lock );
     631
     632
     633
     634//      // SKULLDUGGERY: Even if spurious wake-up is a thing
     635//      // spuriously waking up a kernel thread is not a big deal
     636//      // if it is very rare.
     637//      pthread_cond_wait( &idle.cond, &idle.lock);
     638//      pthread_mutex_unlock( &idle.lock );
     639// }
     640
     641// void wake(processor * this) with( this ) {
     642//      pthread_mutex_lock  (&idle.lock);
     643//      pthread_cond_signal (&idle.cond);
     644//      pthread_mutex_unlock(&idle.lock);
     645// }
    681646
    682647//=============================================================================================
     
    793758// Global Queues
    794759void doregister( cluster     & cltr ) {
    795         lock      ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
    796         push_front( __cfa_dbg_global_clusters.list, cltr );
    797         unlock    ( __cfa_dbg_global_clusters.lock );
     760        lock      ( global_clusters.lock __cfaabi_dbg_ctx2);
     761        push_front( global_clusters.list, cltr );
     762        unlock    ( global_clusters.lock );
    798763}
    799764
    800765void unregister( cluster     & cltr ) {
    801         lock  ( __cfa_dbg_global_clusters.lock __cfaabi_dbg_ctx2);
    802         remove( __cfa_dbg_global_clusters.list, cltr );
    803         unlock( __cfa_dbg_global_clusters.lock );
     766        lock  ( global_clusters.lock __cfaabi_dbg_ctx2);
     767        remove( global_clusters.list, cltr );
     768        unlock( global_clusters.lock );
    804769}
    805770
  • src/libcfa/concurrency/kernel_private.h

    rb21c77a r97397a26  
    4848void BlockInternal(__spinlock_t * locks [], unsigned short count);
    4949void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
    50 void BlockInternal(__finish_callback_fptr_t callback);
    5150void LeaveThread(__spinlock_t * lock, thread_desc * thrd);
    5251
     
    5756void runThread(processor * this, thread_desc * dst);
    5857void finishRunning(processor * this);
    59 void halt(processor * this);
    60 
    61 static inline void wake_fast(processor * this) {
    62         __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
    63         post( this->idleLock );
    64 }
    65 
    66 static inline void wake(processor * this) {
    67         disable_interrupts();
    68         wake_fast(this);
    69         enable_interrupts( __cfaabi_dbg_ctx );
    70 }
     58void terminate(processor * this);
     59void spin(processor * this, unsigned int * spin_count);
    7160
    7261struct event_kernel_t {
     
    7665
    7766extern event_kernel_t * event_kernel;
     67
     68//extern thread_local coroutine_desc * volatile this_coroutine;
     69//extern thread_local thread_desc *    volatile this_thread;
     70//extern thread_local processor *      volatile this_processor;
     71
     72// extern volatile thread_local bool preemption_in_progress;
     73// extern volatile thread_local bool preemption_enabled;
     74// extern volatile thread_local unsigned short disable_preempt_count;
    7875
    7976struct __cfa_kernel_preemption_state_t {
  • src/libcfa/concurrency/monitor.c

    rb21c77a r97397a26  
    297297        this.count = count;
    298298
    299         // Sort monitors based on address
     299        // Sort monitors based on address -> TODO use a sort specialized for small numbers
    300300        __libcfa_small_sort(this.m, count);
    301301
  • src/libcfa/concurrency/preemption.c

    rb21c77a r97397a26  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 17:35:49 2018
    13 // Update Count     : 37
     12// Last Modified On : Mon Apr  9 13:52:39 2018
     13// Update Count     : 36
    1414//
    1515
     
    116116        // If there are still alarms pending, reset the timer
    117117        if( alarms->head ) {
    118                 __cfaabi_dbg_print_buffer_decl( " KERNEL: @%ju(%ju) resetting alarm to %ju.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
     118                __cfaabi_dbg_print_buffer_decl( " KERNEL: @%lu(%lu) resetting alarm to %lu.\n", currtime.tv, __kernel_get_time().tv, (alarms->head->alarm - currtime).tv);
    119119                Duration delta = alarms->head->alarm - currtime;
    120120                Duration caped = max(delta, 50`us);
     
    161161        void disable_interrupts() {
    162162                with( kernelTLS.preemption_state ) {
    163                         #if GCC_VERSION > 50000
    164163                        static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
    165                         #endif
    166164
    167165                        // Set enabled flag to false
     
    192190                        // Check if we need to prempt the thread because an interrupt was missed
    193191                        if( prev == 1 ) {
    194                                 #if GCC_VERSION > 50000
    195192                                static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
    196                                 #endif
    197193
    198194                                // Set enabled flag to true
     
    221217                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    222218                if( prev == 1 ) {
    223                         #if GCC_VERSION > 50000
    224219                        static_assert(__atomic_always_lock_free(sizeof(kernelTLS.preemption_state.enabled), &kernelTLS.preemption_state.enabled), "Must be lock-free");
    225                         #endif
    226220                        // Set enabled flag to true
    227221                        // should be atomic to avoid preemption in the middle of the operation.
     
    260254static void preempt( processor * this ) {
    261255        sigval_t value = { PREEMPT_NORMAL };
     256        pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
     257}
     258
     259// kill wrapper : signal a processor
     260void terminate(processor * this) {
     261        this->do_terminate = true;
     262        sigval_t value = { PREEMPT_TERMINATE };
    262263        pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    263264}
     
    361362        choose(sfp->si_value.sival_int) {
    362363                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
    363                 case PREEMPT_TERMINATE: verify( __atomic_load_n( &kernelTLS.this_processor->do_terminate, __ATOMIC_SEQ_CST ) );
     364                case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate);
    364365                default:
    365366                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     
    375376
    376377        // Clear sighandler mask before context switching.
    377         #if GCC_VERSION > 50000
    378378        static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
    379         #endif
    380379        if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), NULL ) == -1 ) {
    381380                abort( "internal error, sigprocmask" );
     
    480479}
    481480
    482 #ifdef __CFA_WITH_VERIFY__
    483 bool __cfaabi_dbg_in_kernel() {
    484         return !kernelTLS.preemption_state.enabled;
    485 }
    486 #endif
    487 
    488481// Local Variables: //
    489482// mode: c //
  • src/libcfa/fstream

    rb21c77a r97397a26  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 10:20:25 2018
    13 // Update Count     : 131
     12// Last Modified On : Thu Dec  7 15:17:26 2017
     13// Update Count     : 130
    1414//
    1515
     
    5454void open( ofstream &, const char * name );
    5555void close( ofstream & );
    56 ofstream & write( ofstream &, const char * data, size_t size );
     56ofstream & write( ofstream &, const char * data, unsigned long int size );
    5757int fmt( ofstream &, const char fmt[], ... );
    5858
     
    7474void open( ifstream & is, const char * name );
    7575void close( ifstream & is );
    76 ifstream & read( ifstream & is, char * data, size_t size );
     76ifstream & read( ifstream & is, char * data, unsigned long int size );
    7777ifstream & ungetc( ifstream & is, char c );
    7878int fmt( ifstream &, const char fmt[], ... );
  • src/libcfa/fstream.c

    rb21c77a r97397a26  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 17:02:56 2018
    13 // Update Count     : 281
     12// Last Modified On : Sat Dec  9 09:31:23 2017
     13// Update Count     : 275
    1414//
    1515
     
    116116} // close
    117117
    118 ofstream & write( ofstream & os, const char * data, size_t size ) {
     118ofstream & write( ofstream & os, const char * data, unsigned long int size ) {
    119119        if ( fail( os ) ) {
    120120                fprintf( stderr, "attempt write I/O on failed stream\n" );
     
    198198} // close
    199199
    200 ifstream & read( ifstream & is, char * data, size_t size ) {
     200ifstream & read( ifstream & is, char * data, unsigned long int size ) {
    201201        if ( fail( is ) ) {
    202202                fprintf( stderr, "attempt read I/O on failed stream\n" );
  • src/libcfa/iostream

    rb21c77a r97397a26  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  2 08:07:55 2018
    13 // Update Count     : 153
     12// Last Modified On : Sat Apr 28 13:08:24 2018
     13// Update Count     : 152
    1414//
    1515
     
    5656// implement writable for intrinsic types
    5757
    58 forall( dtype ostype | ostream( ostype ) ) {
    59         ostype & ?|?( ostype &, _Bool );
     58forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, _Bool );
    6059
    61         ostype & ?|?( ostype &, char );
    62         ostype & ?|?( ostype &, signed char );
    63         ostype & ?|?( ostype &, unsigned char );
     60forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, char );
     61forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, signed char );
     62forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned char );
    6463
    65         ostype & ?|?( ostype &, short int );
    66         ostype & ?|?( ostype &, unsigned short int );
    67         ostype & ?|?( ostype &, int );
    68         ostype & ?|?( ostype &, unsigned int );
    69         ostype & ?|?( ostype &, long int );
    70         ostype & ?|?( ostype &, long long int );
    71         ostype & ?|?( ostype &, unsigned long int );
    72         ostype & ?|?( ostype &, unsigned long long int );
     64forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, short int );
     65forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned short int );
     66forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, int );
     67forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned int );
     68forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long int );
     69forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long long int );
     70forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned long int );
     71forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned long long int );
    7372
    74         ostype & ?|?( ostype &, float ); // FIX ME: should not be required
    75         ostype & ?|?( ostype &, double );
    76         ostype & ?|?( ostype &, long double );
     73forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, float ); // FIX ME: should not be required
     74forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, double );
     75forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long double );
    7776
    78         ostype & ?|?( ostype &, float _Complex );
    79         ostype & ?|?( ostype &, double _Complex );
    80         ostype & ?|?( ostype &, long double _Complex );
     77forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, float _Complex );
     78forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, double _Complex );
     79forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long double _Complex );
    8180
    82         ostype & ?|?( ostype &, const char * );
    83         // ostype & ?|?( ostype &, const char16_t * );
     81forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char * );
     82//forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char16_t * );
    8483#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    85         // ostype & ?|?( ostype &, const char32_t * );
     84//forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char32_t * );
    8685#endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    87         // ostype & ?|?( ostype &, const wchar_t * );
    88         ostype & ?|?( ostype &, const void * );
    89 
    90         // manipulators
    91         ostype & ?|?( ostype &, ostype & (*)( ostype & ) );
    92         ostype & endl( ostype & );
    93         ostype & sep( ostype & );
    94         ostype & sepTuple( ostype & );
    95         ostype & sepOn( ostype & );
    96         ostype & sepOff( ostype & );
    97         ostype & sepDisable( ostype & );
    98         ostype & sepEnable( ostype & );
    99 } // distribution
     86//forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const wchar_t * );
     87forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const void * );
    10088
    10189// tuples
    10290forall( dtype ostype, otype T, ttype Params | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } )
    10391ostype & ?|?( ostype & os, T arg, Params rest );
     92
     93// manipulators
     94forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, ostype & (*)( ostype & ) );
     95forall( dtype ostype | ostream( ostype ) ) ostype & endl( ostype & );
     96forall( dtype ostype | ostream( ostype ) ) ostype & sep( ostype & );
     97forall( dtype ostype | ostream( ostype ) ) ostype & sepTuple( ostype & );
     98forall( dtype ostype | ostream( ostype ) ) ostype & sepOn( ostype & );
     99forall( dtype ostype | ostream( ostype ) ) ostype & sepOff( ostype & );
     100forall( dtype ostype | ostream( ostype ) ) ostype & sepDisable( ostype & );
     101forall( dtype ostype | ostream( ostype ) ) ostype & sepEnable( ostype & );
    104102
    105103// writes the range [begin, end) to the given stream
     
    126124}; // readable
    127125
    128 forall( dtype istype | istream( istype ) ) {
    129         istype & ?|?( istype &, _Bool & );
     126forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, _Bool & );
    130127
    131         istype & ?|?( istype &, char & );
    132         istype & ?|?( istype &, signed char & );
    133         istype & ?|?( istype &, unsigned char & );
     128forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, char & );
     129forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, signed char & );
     130forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned char & );
    134131
    135         istype & ?|?( istype &, short int & );
    136         istype & ?|?( istype &, unsigned short int & );
    137         istype & ?|?( istype &, int & );
    138         istype & ?|?( istype &, unsigned int & );
    139         istype & ?|?( istype &, long int & );
    140         istype & ?|?( istype &, long long int & );
    141         istype & ?|?( istype &, unsigned long int & );
    142         istype & ?|?( istype &, unsigned long long int & );
     132forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, short int & );
     133forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned short int & );
     134forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, int & );
     135forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned int & );
     136forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long int & );
     137forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long long int & );
     138forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned long int & );
     139forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned long long int & );
    143140
    144         istype & ?|?( istype &, float & );
    145         istype & ?|?( istype &, double & );
    146         istype & ?|?( istype &, long double & );
     141forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, float & );
     142forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, double & );
     143forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long double & );
    147144
    148         istype & ?|?( istype &, float _Complex & );
    149         istype & ?|?( istype &, double _Complex & );
    150         istype & ?|?( istype &, long double _Complex & );
     145forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, float _Complex & );
     146forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, double _Complex & );
     147forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long double _Complex & );
    151148
    152         // manipulators
    153         istype & ?|?( istype &, istype & (*)( istype & ) );
    154         istype & endl( istype & is );
    155 } // distribution
     149// manipulators
     150forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, istype & (*)( istype & ) );
     151forall( dtype istype | istream( istype ) ) istype & endl( istype & is );
    156152
    157153struct _Istream_cstrUC { char * s; };
  • src/libcfa/iostream.c

    rb21c77a r97397a26  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  2 08:24:56 2018
    13 // Update Count     : 471
     12// Last Modified On : Sat Apr 28 13:08:25 2018
     13// Update Count     : 469
    1414//
    1515
     
    2626}
    2727
    28 forall( dtype ostype | ostream( ostype ) ) {
    29         ostype & ?|?( ostype & os, _Bool b ) {
    30                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    31                 fmt( os, "%s", b ? "true" : "false" );
    32                 return os;
    33         } // ?|?
    34 
    35         ostype & ?|?( ostype & os, char ch ) {
    36                 fmt( os, "%c", ch );
    37                 if ( ch == '\n' ) setNL( os, true );
     28forall( dtype ostype | ostream( ostype ) )
     29ostype & ?|?( ostype & os, _Bool b ) {
     30        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     31        fmt( os, "%s", b ? "true" : "false" );
     32        return os;
     33} // ?|?
     34
     35forall( dtype ostype | ostream( ostype ) )
     36ostype & ?|?( ostype & os, char ch ) {
     37        fmt( os, "%c", ch );
     38        if ( ch == '\n' ) setNL( os, true );
     39        sepOff( os );
     40        return os;
     41} // ?|?
     42
     43forall( dtype ostype | ostream( ostype ) )
     44ostype & ?|?( ostype & os, signed char c ) {
     45        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     46        fmt( os, "%hhd", c );
     47        return os;
     48} // ?|?
     49
     50forall( dtype ostype | ostream( ostype ) )
     51ostype & ?|?( ostype & os, unsigned char c ) {
     52        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     53        fmt( os, "%hhu", c );
     54        return os;
     55} // ?|?
     56
     57forall( dtype ostype | ostream( ostype ) )
     58ostype & ?|?( ostype & os, short int si ) {
     59        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     60        fmt( os, "%hd", si );
     61        return os;
     62} // ?|?
     63
     64forall( dtype ostype | ostream( ostype ) )
     65ostype & ?|?( ostype & os, unsigned short int usi ) {
     66        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     67        fmt( os, "%hu", usi );
     68        return os;
     69} // ?|?
     70
     71forall( dtype ostype | ostream( ostype ) )
     72ostype & ?|?( ostype & os, int i ) {
     73        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     74        fmt( os, "%d", i );
     75        return os;
     76} // ?|?
     77
     78forall( dtype ostype | ostream( ostype ) )
     79ostype & ?|?( ostype & os, unsigned int ui ) {
     80        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     81        fmt( os, "%u", ui );
     82        return os;
     83} // ?|?
     84
     85forall( dtype ostype | ostream( ostype ) )
     86ostype & ?|?( ostype & os, long int li ) {
     87        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     88        fmt( os, "%ld", li );
     89        return os;
     90} // ?|?
     91
     92forall( dtype ostype | ostream( ostype ) )
     93ostype & ?|?( ostype & os, unsigned long int uli ) {
     94        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     95        fmt( os, "%lu", uli );
     96        return os;
     97} // ?|?
     98
     99forall( dtype ostype | ostream( ostype ) )
     100ostype & ?|?( ostype & os, long long int lli ) {
     101        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     102        fmt( os, "%lld", lli );
     103        return os;
     104} // ?|?
     105
     106forall( dtype ostype | ostream( ostype ) )
     107ostype & ?|?( ostype & os, unsigned long long int ulli ) {
     108        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     109        fmt( os, "%llu", ulli );
     110        return os;
     111} // ?|?
     112
     113forall( dtype ostype | ostream( ostype ) )
     114ostype & ?|?( ostype & os, float f ) {
     115        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     116        fmt( os, "%g", f );
     117        return os;
     118} // ?|?
     119
     120forall( dtype ostype | ostream( ostype ) )
     121ostype & ?|?( ostype & os, double d ) {
     122        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     123        fmt( os, "%.*lg", DBL_DIG, d );
     124        return os;
     125} // ?|?
     126
     127forall( dtype ostype | ostream( ostype ) )
     128ostype & ?|?( ostype & os, long double ld ) {
     129        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     130        fmt( os, "%.*Lg", LDBL_DIG, ld );
     131        return os;
     132} // ?|?
     133
     134forall( dtype ostype | ostream( ostype ) )
     135ostype & ?|?( ostype & os, float _Complex fc ) {
     136        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     137        fmt( os, "%g%+gi", crealf( fc ), cimagf( fc ) );
     138        return os;
     139} // ?|?
     140
     141forall( dtype ostype | ostream( ostype ) )
     142ostype & ?|?( ostype & os, double _Complex dc ) {
     143        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     144        fmt( os, "%.*lg%+.*lgi", DBL_DIG, creal( dc ), DBL_DIG, cimag( dc ) );
     145        return os;
     146} // ?|?
     147
     148forall( dtype ostype | ostream( ostype ) )
     149ostype & ?|?( ostype & os, long double _Complex ldc ) {
     150        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     151        fmt( os, "%.*Lg%+.*Lgi", LDBL_DIG, creall( ldc ), LDBL_DIG, cimagl( ldc ) );
     152        return os;
     153} // ?|?
     154
     155forall( dtype ostype | ostream( ostype ) )
     156ostype & ?|?( ostype & os, const char * str ) {
     157        enum { Open = 1, Close, OpenClose };
     158        static const unsigned char mask[256] @= {
     159                // opening delimiters, no space after
     160                ['('] : Open, ['['] : Open, ['{'] : Open,
     161                ['='] : Open, ['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open,
     162                [(unsigned char)'¡'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open,
     163                // closing delimiters, no space before
     164                [','] : Close, ['.'] : Close, [';'] : Close, ['!'] : Close, ['?'] : Close,
     165                ['%'] : Close, [(unsigned char)'¢'] : Close, [(unsigned char)'»'] : Close,
     166                [')'] : Close, [']'] : Close, ['}'] : Close,
     167                // opening-closing delimiters, no space before or after
     168                ['\''] : OpenClose, ['`'] : OpenClose, ['"'] : OpenClose, [':'] : OpenClose,
     169                [' '] : OpenClose, ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace
     170        }; // mask
     171
     172  if ( str[0] == '\0' ) { sepOff( os ); return os; }            // null string => no separator
     173
     174        // first character IS NOT spacing or closing punctuation => add left separator
     175        unsigned char ch = str[0];                                                      // must make unsigned
     176        if ( sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {
     177                fmt( os, "%s", sepGetCur( os ) );
     178        } // if
     179
     180        // if string starts line, must reset to determine open state because separator is off
     181        sepReset( os );                                                                         // reset separator
     182
     183        // last character IS spacing or opening punctuation => turn off separator for next item
     184        size_t len = strlen( str );
     185        ch = str[len - 1];                                                                      // must make unsigned
     186        if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
     187                sepOn( os );
     188        } else {
    38189                sepOff( os );
    39                 return os;
    40         } // ?|?
    41 
    42         ostype & ?|?( ostype & os, signed char c ) {
    43                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    44                 fmt( os, "%hhd", c );
    45                 return os;
    46         } // ?|?
    47 
    48         ostype & ?|?( ostype & os, unsigned char c ) {
    49                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    50                 fmt( os, "%hhu", c );
    51                 return os;
    52         } // ?|?
    53 
    54         ostype & ?|?( ostype & os, short int si ) {
    55                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    56                 fmt( os, "%hd", si );
    57                 return os;
    58         } // ?|?
    59 
    60         ostype & ?|?( ostype & os, unsigned short int usi ) {
    61                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    62                 fmt( os, "%hu", usi );
    63                 return os;
    64         } // ?|?
    65 
    66         ostype & ?|?( ostype & os, int i ) {
    67                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    68                 fmt( os, "%d", i );
    69                 return os;
    70         } // ?|?
    71 
    72         ostype & ?|?( ostype & os, unsigned int ui ) {
    73                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    74                 fmt( os, "%u", ui );
    75                 return os;
    76         } // ?|?
    77 
    78         ostype & ?|?( ostype & os, long int li ) {
    79                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    80                 fmt( os, "%ld", li );
    81                 return os;
    82         } // ?|?
    83 
    84         ostype & ?|?( ostype & os, unsigned long int uli ) {
    85                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    86                 fmt( os, "%lu", uli );
    87                 return os;
    88         } // ?|?
    89 
    90         ostype & ?|?( ostype & os, long long int lli ) {
    91                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    92                 fmt( os, "%lld", lli );
    93                 return os;
    94         } // ?|?
    95 
    96         ostype & ?|?( ostype & os, unsigned long long int ulli ) {
    97                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    98                 fmt( os, "%llu", ulli );
    99                 return os;
    100         } // ?|?
    101 
    102         ostype & ?|?( ostype & os, float f ) {
    103                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    104                 fmt( os, "%g", f );
    105                 return os;
    106         } // ?|?
    107 
    108         ostype & ?|?( ostype & os, double d ) {
    109                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    110                 fmt( os, "%.*lg", DBL_DIG, d );
    111                 return os;
    112         } // ?|?
    113 
    114         ostype & ?|?( ostype & os, long double ld ) {
    115                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    116                 fmt( os, "%.*Lg", LDBL_DIG, ld );
    117                 return os;
    118         } // ?|?
    119 
    120         ostype & ?|?( ostype & os, float _Complex fc ) {
    121                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    122                 fmt( os, "%g%+gi", crealf( fc ), cimagf( fc ) );
    123                 return os;
    124         } // ?|?
    125 
    126         ostype & ?|?( ostype & os, double _Complex dc ) {
    127                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    128                 fmt( os, "%.*lg%+.*lgi", DBL_DIG, creal( dc ), DBL_DIG, cimag( dc ) );
    129                 return os;
    130         } // ?|?
    131 
    132         ostype & ?|?( ostype & os, long double _Complex ldc ) {
    133                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    134                 fmt( os, "%.*Lg%+.*Lgi", LDBL_DIG, creall( ldc ), LDBL_DIG, cimagl( ldc ) );
    135                 return os;
    136         } // ?|?
    137 
    138         ostype & ?|?( ostype & os, const char * str ) {
    139                 enum { Open = 1, Close, OpenClose };
    140                 static const unsigned char mask[256] @= {
    141                         // opening delimiters, no space after
    142                         ['('] : Open, ['['] : Open, ['{'] : Open,
    143                         ['='] : Open, ['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open,
    144                         [(unsigned char)'¡'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open,
    145                         // closing delimiters, no space before
    146                         [','] : Close, ['.'] : Close, [';'] : Close, ['!'] : Close, ['?'] : Close,
    147                         ['%'] : Close, [(unsigned char)'¢'] : Close, [(unsigned char)'»'] : Close,
    148                         [')'] : Close, [']'] : Close, ['}'] : Close,
    149                         // opening-closing delimiters, no space before or after
    150                         ['\''] : OpenClose, ['`'] : OpenClose, ['"'] : OpenClose, [':'] : OpenClose,
    151                         [' '] : OpenClose, ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace
    152                 }; // mask
    153 
    154           if ( str[0] == '\0' ) { sepOff( os ); return os; } // null string => no separator
    155 
    156                 // first character IS NOT spacing or closing punctuation => add left separator
    157                 unsigned char ch = str[0];                                              // must make unsigned
    158                 if ( sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {
    159                         fmt( os, "%s", sepGetCur( os ) );
    160                 } // if
    161 
    162                 // if string starts line, must reset to determine open state because separator is off
    163                 sepReset( os );                                                                 // reset separator
    164 
    165                 // last character IS spacing or opening punctuation => turn off separator for next item
    166                 size_t len = strlen( str );
    167                 ch = str[len - 1];                                                              // must make unsigned
    168                 if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
    169                         sepOn( os );
    170                 } else {
    171                         sepOff( os );
    172                 } // if
    173                 if ( ch == '\n' ) setNL( os, true );                    // check *AFTER* sepPrt call above as it resets NL flag
    174                 return write( os, str, len );
    175         } // ?|?
    176 
    177 //      ostype & ?|?( ostype & os, const char16_t * str ) {
    178 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    179 //              fmt( os, "%ls", str );
    180 //              return os;
    181 //      } // ?|?
     190        } // if
     191        if ( ch == '\n' ) setNL( os, true );                            // check *AFTER* sepPrt call above as it resets NL flag
     192        return write( os, str, len );
     193} // ?|?
     194
     195// forall( dtype ostype | ostream( ostype ) )
     196// ostype & ?|?( ostype & os, const char16_t * str ) {
     197//      if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     198//      fmt( os, "%ls", str );
     199//      return os;
     200// } // ?|?
    182201
    183202// #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    184 //      ostype & ?|?( ostype & os, const char32_t * str ) {
    185 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    186 //              fmt( os, "%ls", str );
    187 //              return os;
    188 //      } // ?|?
     203// forall( dtype ostype | ostream( ostype ) )
     204// ostype & ?|?( ostype & os, const char32_t * str ) {
     205//      if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     206//      fmt( os, "%ls", str );
     207//      return os;
     208// } // ?|?
    189209// #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    190210
    191 //      ostype & ?|?( ostype & os, const wchar_t * str ) {
    192 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    193 //              fmt( os, "%ls", str );
    194 //              return os;
    195 //      } // ?|?
    196 
    197         ostype & ?|?( ostype & os, const void * p ) {
    198                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    199                 fmt( os, "%p", p );
    200                 return os;
    201         } // ?|?
    202 
    203 
    204         // manipulators
    205         ostype & ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
    206                 return manip( os );
    207         } // ?|?
    208 
    209         ostype & sep( ostype & os ) {
    210                 os | sepGet( os );
    211                 return os;
    212         } // sep
    213 
    214         ostype & sepTuple( ostype & os ) {
    215                 os | sepGetTuple( os );
    216                 return os;
    217         } // sepTuple
    218 
    219         ostype & endl( ostype & os ) {
    220                 os | '\n';
    221                 setNL( os, true );
    222                 flush( os );
    223                 sepOff( os );                                                                   // prepare for next line
    224                 return os;
    225         } // endl
    226 
    227         ostype & sepOn( ostype & os ) {
    228                 sepOn( os );
    229                 return os;
    230         } // sepOn
    231 
    232         ostype & sepOff( ostype & os ) {
    233                 sepOff( os );
    234                 return os;
    235         } // sepOff
    236 
    237         ostype & sepEnable( ostype & os ) {
    238                 sepEnable( os );
    239                 return os;
    240         } // sepEnable
    241 
    242         ostype & sepDisable( ostype & os ) {
    243                 sepDisable( os );
    244                 return os;
    245         } // sepDisable
    246 } // distribution
     211// forall( dtype ostype | ostream( ostype ) )
     212// ostype & ?|?( ostype & os, const wchar_t * str ) {
     213//      if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     214//      fmt( os, "%ls", str );
     215//      return os;
     216// } // ?|?
     217
     218forall( dtype ostype | ostream( ostype ) )
     219ostype & ?|?( ostype & os, const void * p ) {
     220        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     221        fmt( os, "%p", p );
     222        return os;
     223} // ?|?
    247224
    248225
     
    257234} // ?|?
    258235
     236
     237// manipulators
     238forall( dtype ostype | ostream( ostype ) )
     239ostype & ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
     240        return manip( os );
     241} // ?|?
     242
     243forall( dtype ostype | ostream( ostype ) )
     244ostype & sep( ostype & os ) {
     245        os | sepGet( os );
     246        return os;
     247} // sep
     248
     249forall( dtype ostype | ostream( ostype ) )
     250ostype & sepTuple( ostype & os ) {
     251        os | sepGetTuple( os );
     252        return os;
     253} // sepTuple
     254
     255forall( dtype ostype | ostream( ostype ) )
     256ostype & endl( ostype & os ) {
     257        os | '\n';
     258        setNL( os, true );
     259        flush( os );
     260        sepOff( os );                                                                           // prepare for next line
     261        return os;
     262} // endl
     263
     264forall( dtype ostype | ostream( ostype ) )
     265ostype & sepOn( ostype & os ) {
     266        sepOn( os );
     267        return os;
     268} // sepOn
     269
     270forall( dtype ostype | ostream( ostype ) )
     271ostype & sepOff( ostype & os ) {
     272        sepOff( os );
     273        return os;
     274} // sepOff
     275
     276forall( dtype ostype | ostream( ostype ) )
     277ostype & sepEnable( ostype & os ) {
     278        sepEnable( os );
     279        return os;
     280} // sepEnable
     281
     282forall( dtype ostype | ostream( ostype ) )
     283ostype & sepDisable( ostype & os ) {
     284        sepDisable( os );
     285        return os;
     286} // sepDisable
     287
    259288//---------------------------------------
    260289
    261 // writes the range [begin, end) to the given stream
    262290forall( dtype ostype, otype elt_type | writeable( elt_type, ostype ), otype iterator_type | iterator( iterator_type, elt_type ) )
    263291void write( iterator_type begin, iterator_type end, ostype & os ) {
     
    274302//---------------------------------------
    275303
    276 forall( dtype istype | istream( istype ) ) {
    277         istype & ?|?( istype & is, _Bool & b ) {
    278                 char val[6];
    279                 fmt( is, "%5s", val );
    280                 if ( strcmp( val, "true" ) == 0 ) b = true;
    281                 else if ( strcmp( val, "false" ) == 0 ) b = false;
    282                 else {
    283                         fprintf( stderr, "invalid _Bool constant\n" );
    284                         abort();
    285                 } // if
    286                 return is;
    287         } // ?|?
    288 
    289         istype & ?|?( istype & is, char & c ) {
    290                 fmt( is, "%c", &c );                                                    // must pass pointer through varg to fmt
    291                 return is;
    292         } // ?|?
    293 
    294         istype & ?|?( istype & is, signed char & sc ) {
    295                 fmt( is, "%hhd", &sc );
    296                 return is;
    297         } // ?|?
    298 
    299         istype & ?|?( istype & is, unsigned char & usc ) {
    300                 fmt( is, "%hhu", &usc );
    301                 return is;
    302         } // ?|?
    303 
    304         istype & ?|?( istype & is, short int & si ) {
    305                 fmt( is, "%hd", &si );
    306                 return is;
    307         } // ?|?
    308 
    309         istype & ?|?( istype & is, unsigned short int & usi ) {
    310                 fmt( is, "%hu", &usi );
    311                 return is;
    312         } // ?|?
    313 
    314         istype & ?|?( istype & is, int & i ) {
    315                 fmt( is, "%d", &i );
    316                 return is;
    317         } // ?|?
    318 
    319         istype & ?|?( istype & is, unsigned int & ui ) {
    320                 fmt( is, "%u", &ui );
    321                 return is;
    322         } // ?|?
    323 
    324         istype & ?|?( istype & is, long int & li ) {
    325                 fmt( is, "%ld", &li );
    326                 return is;
    327         } // ?|?
    328 
    329         istype & ?|?( istype & is, unsigned long int & ulli ) {
    330                 fmt( is, "%lu", &ulli );
    331                 return is;
    332         } // ?|?
    333 
    334         istype & ?|?( istype & is, long long int & lli ) {
    335                 fmt( is, "%lld", &lli );
    336                 return is;
    337         } // ?|?
    338 
    339         istype & ?|?( istype & is, unsigned long long int & ulli ) {
    340                 fmt( is, "%llu", &ulli );
    341                 return is;
    342         } // ?|?
    343 
    344 
    345         istype & ?|?( istype & is, float & f ) {
    346                 fmt( is, "%f", &f );
    347                 return is;
    348         } // ?|?
    349 
    350         istype & ?|?( istype & is, double & d ) {
    351                 fmt( is, "%lf", &d );
    352                 return is;
    353         } // ?|?
    354 
    355         istype & ?|?( istype & is, long double & ld ) {
    356                 fmt( is, "%Lf", &ld );
    357                 return is;
    358         } // ?|?
    359 
    360 
    361         istype & ?|?( istype & is, float _Complex & fc ) {
    362                 float re, im;
    363                 fmt( is, "%g%gi", &re, &im );
    364                 fc = re + im * _Complex_I;
    365                 return is;
    366         } // ?|?
    367 
    368         istype & ?|?( istype & is, double _Complex & dc ) {
    369                 double re, im;
    370                 fmt( is, "%lf%lfi", &re, &im );
    371                 dc = re + im * _Complex_I;
    372                 return is;
    373         } // ?|?
    374 
    375         istype & ?|?( istype & is, long double _Complex & ldc ) {
    376                 long double re, im;
    377                 fmt( is, "%Lf%Lfi", &re, &im );
    378                 ldc = re + im * _Complex_I;
    379                 return is;
    380         } // ?|?
    381 
    382 
    383         // manipulators
    384         istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
    385                 return manip( is );
    386         } // ?|?
    387 
    388         istype & endl( istype & is ) {
    389                 fmt( is, "%*[ \t\f\n\r\v]" );                                   // ignore whitespace
    390                 return is;
    391         } // endl
    392 } // distribution
     304forall( dtype istype | istream( istype ) )
     305istype & ?|?( istype & is, _Bool & b ) {
     306        char val[6];
     307        fmt( is, "%5s", val );
     308        if ( strcmp( val, "true" ) == 0 ) b = true;
     309        else if ( strcmp( val, "false" ) == 0 ) b = false;
     310        else {
     311                fprintf( stderr, "invalid _Bool constant\n" );
     312                abort();
     313        } // if
     314        return is;
     315} // ?|?
     316
     317forall( dtype istype | istream( istype ) )
     318istype & ?|?( istype & is, char & c ) {
     319        fmt( is, "%c", &c );                                                            // must pass pointer through varg to fmt
     320        return is;
     321} // ?|?
     322
     323forall( dtype istype | istream( istype ) )
     324istype & ?|?( istype & is, signed char & sc ) {
     325        fmt( is, "%hhd", &sc );
     326        return is;
     327} // ?|?
     328
     329forall( dtype istype | istream( istype ) )
     330istype & ?|?( istype & is, unsigned char & usc ) {
     331        fmt( is, "%hhu", &usc );
     332        return is;
     333} // ?|?
     334
     335forall( dtype istype | istream( istype ) )
     336istype & ?|?( istype & is, short int & si ) {
     337        fmt( is, "%hd", &si );
     338        return is;
     339} // ?|?
     340
     341forall( dtype istype | istream( istype ) )
     342istype & ?|?( istype & is, unsigned short int & usi ) {
     343        fmt( is, "%hu", &usi );
     344        return is;
     345} // ?|?
     346
     347forall( dtype istype | istream( istype ) )
     348istype & ?|?( istype & is, int & i ) {
     349        fmt( is, "%d", &i );
     350        return is;
     351} // ?|?
     352
     353forall( dtype istype | istream( istype ) )
     354istype & ?|?( istype & is, unsigned int & ui ) {
     355        fmt( is, "%u", &ui );
     356        return is;
     357} // ?|?
     358
     359forall( dtype istype | istream( istype ) )
     360istype & ?|?( istype & is, long int & li ) {
     361        fmt( is, "%ld", &li );
     362        return is;
     363} // ?|?
     364
     365forall( dtype istype | istream( istype ) )
     366istype & ?|?( istype & is, unsigned long int & ulli ) {
     367        fmt( is, "%lu", &ulli );
     368        return is;
     369} // ?|?
     370
     371forall( dtype istype | istream( istype ) )
     372istype & ?|?( istype & is, long long int & lli ) {
     373        fmt( is, "%lld", &lli );
     374        return is;
     375} // ?|?
     376
     377forall( dtype istype | istream( istype ) )
     378istype & ?|?( istype & is, unsigned long long int & ulli ) {
     379        fmt( is, "%llu", &ulli );
     380        return is;
     381} // ?|?
     382
     383
     384forall( dtype istype | istream( istype ) )
     385istype & ?|?( istype & is, float & f ) {
     386        fmt( is, "%f", &f );
     387        return is;
     388} // ?|?
     389
     390forall( dtype istype | istream( istype ) )
     391istype & ?|?( istype & is, double & d ) {
     392        fmt( is, "%lf", &d );
     393        return is;
     394} // ?|?
     395
     396forall( dtype istype | istream( istype ) )
     397istype & ?|?( istype & is, long double & ld ) {
     398        fmt( is, "%Lf", &ld );
     399        return is;
     400} // ?|?
     401
     402
     403forall( dtype istype | istream( istype ) )
     404istype & ?|?( istype & is, float _Complex & fc ) {
     405        float re, im;
     406        fmt( is, "%g%gi", &re, &im );
     407        fc = re + im * _Complex_I;
     408        return is;
     409} // ?|?
     410
     411forall( dtype istype | istream( istype ) )
     412istype & ?|?( istype & is, double _Complex & dc ) {
     413        double re, im;
     414        fmt( is, "%lf%lfi", &re, &im );
     415        dc = re + im * _Complex_I;
     416        return is;
     417} // ?|?
     418
     419forall( dtype istype | istream( istype ) )
     420istype & ?|?( istype & is, long double _Complex & ldc ) {
     421        long double re, im;
     422        fmt( is, "%Lf%Lfi", &re, &im );
     423        ldc = re + im * _Complex_I;
     424        return is;
     425} // ?|?
     426
     427forall( dtype istype | istream( istype ) )
     428istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
     429        return manip( is );
     430} // ?|?
     431
     432forall( dtype istype | istream( istype ) )
     433istype & endl( istype & is ) {
     434        fmt( is, "%*[ \t\f\n\r\v]" );                                           // ignore whitespace
     435        return is;
     436} // endl
    393437
    394438_Istream_cstrUC cstr( char * str ) { return (_Istream_cstrUC){ str }; }
  • src/libcfa/rational

    rb21c77a r97397a26  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Sat Jun  2 09:10:01 2018
    15 // Update Count     : 105
     14// Last Modified On : Wed Dec  6 23:12:53 2017
     15// Update Count     : 97
    1616//
    1717
     
    4646// implementation
    4747
    48 forall( otype RationalImpl | arithmetic( RationalImpl ) ) {
    49         struct Rational {
    50                 RationalImpl numerator, denominator;                    // invariant: denominator > 0
    51         }; // Rational
     48forall( otype RationalImpl | arithmetic( RationalImpl ) )
     49struct Rational {
     50        RationalImpl numerator, denominator;                            // invariant: denominator > 0
     51}; // Rational
    5252
    53         // constructors
     53// constructors
    5454
    55         void ?{}( Rational(RationalImpl) & r );
    56         void ?{}( Rational(RationalImpl) & r, RationalImpl n );
    57         void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d );
    58         void ?{}( Rational(RationalImpl) & r, zero_t );
    59         void ?{}( Rational(RationalImpl) & r, one_t );
     55forall( otype RationalImpl | arithmetic( RationalImpl ) )
     56void ?{}( Rational(RationalImpl) & r );
    6057
    61         // numerator/denominator getter
     58forall( otype RationalImpl | arithmetic( RationalImpl ) )
     59void ?{}( Rational(RationalImpl) & r, RationalImpl n );
    6260
    63         RationalImpl numerator( Rational(RationalImpl) r );
    64         RationalImpl denominator( Rational(RationalImpl) r );
    65         [ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src );
     61forall( otype RationalImpl | arithmetic( RationalImpl ) )
     62void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d );
    6663
    67         // numerator/denominator setter
     64forall( otype RationalImpl | arithmetic( RationalImpl ) )
     65void ?{}( Rational(RationalImpl) & r, zero_t );
    6866
    69         RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n );
    70         RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d );
     67forall( otype RationalImpl | arithmetic( RationalImpl ) )
     68void ?{}( Rational(RationalImpl) & r, one_t );
    7169
    72         // comparison
     70// numerator/denominator getter
    7371
    74         int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    75         int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    76         int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    77         int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    78         int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    79         int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     72forall( otype RationalImpl | arithmetic( RationalImpl ) )
     73RationalImpl numerator( Rational(RationalImpl) r );
    8074
    81         // arithmetic
     75forall( otype RationalImpl | arithmetic( RationalImpl ) )
     76RationalImpl denominator( Rational(RationalImpl) r );
    8277
    83         Rational(RationalImpl) +?( Rational(RationalImpl) r );
    84         Rational(RationalImpl) -?( Rational(RationalImpl) r );
    85         Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    86         Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    87         Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    88         Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     78forall( otype RationalImpl | arithmetic( RationalImpl ) )
     79[ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src );
    8980
    90         // I/O
    91         forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    92         istype & ?|?( istype &, Rational(RationalImpl) & );
     81// numerator/denominator setter
    9382
    94         forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
    95         ostype & ?|?( ostype &, Rational(RationalImpl ) );
    96 } // distribution
     83forall( otype RationalImpl | arithmetic( RationalImpl ) )
     84RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n );
     85
     86forall( otype RationalImpl | arithmetic( RationalImpl ) )
     87RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d );
     88
     89// comparison
     90
     91forall( otype RationalImpl | arithmetic( RationalImpl ) )
     92int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     93
     94forall( otype RationalImpl | arithmetic( RationalImpl ) )
     95int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     96
     97forall( otype RationalImpl | arithmetic( RationalImpl ) )
     98int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     99
     100forall( otype RationalImpl | arithmetic( RationalImpl ) )
     101int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     102
     103forall( otype RationalImpl | arithmetic( RationalImpl ) )
     104int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     105
     106forall( otype RationalImpl | arithmetic( RationalImpl ) )
     107int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     108
     109// arithmetic
     110
     111forall( otype RationalImpl | arithmetic( RationalImpl ) )
     112Rational(RationalImpl) +?( Rational(RationalImpl) r );
     113
     114forall( otype RationalImpl | arithmetic( RationalImpl ) )
     115Rational(RationalImpl) -?( Rational(RationalImpl) r );
     116
     117forall( otype RationalImpl | arithmetic( RationalImpl ) )
     118Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     119
     120forall( otype RationalImpl | arithmetic( RationalImpl ) )
     121Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     122
     123forall( otype RationalImpl | arithmetic( RationalImpl ) )
     124Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     125
     126forall( otype RationalImpl | arithmetic( RationalImpl ) )
     127Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    97128
    98129// conversion
     
    102133Rational(RationalImpl) narrow( double f, RationalImpl md );
    103134
     135// I/O
     136forall( otype RationalImpl | arithmetic( RationalImpl ) )
     137forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
     138istype & ?|?( istype &, Rational(RationalImpl) & );
     139
     140forall( otype RationalImpl | arithmetic( RationalImpl ) )
     141forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
     142ostype & ?|?( ostype &, Rational(RationalImpl ) );
     143
    104144// Local Variables: //
    105145// mode: c //
  • src/libcfa/rational.c

    rb21c77a r97397a26  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  2 09:24:33 2018
    13 // Update Count     : 162
     12// Last Modified On : Wed Dec  6 23:13:58 2017
     13// Update Count     : 156
    1414//
    1515
     
    1818#include "stdlib"
    1919
    20 forall( otype RationalImpl | arithmetic( RationalImpl ) ) {
    21         // helper routines
    22 
    23         // Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce
    24         // rationals.  alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
    25         static RationalImpl gcd( RationalImpl a, RationalImpl b ) {
    26                 for ( ;; ) {                                                                    // Euclid's algorithm
    27                         RationalImpl r = a % b;
    28                   if ( r == (RationalImpl){0} ) break;
    29                         a = b;
    30                         b = r;
    31                 } // for
    32                 return b;
    33         } // gcd
    34 
    35         static RationalImpl simplify( RationalImpl & n, RationalImpl & d ) {
    36                 if ( d == (RationalImpl){0} ) {
    37                         serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
    38                         exit( EXIT_FAILURE );
    39                 } // exit
    40                 if ( d < (RationalImpl){0} ) { d = -d; n = -n; } // move sign to numerator
    41                 return gcd( abs( n ), d );                                              // simplify
    42         } // Rationalnumber::simplify
    43 
    44         // constructors
    45 
    46         void ?{}( Rational(RationalImpl) & r ) {
    47                 r{ (RationalImpl){0}, (RationalImpl){1} };
    48         } // rational
    49 
    50         void ?{}( Rational(RationalImpl) & r, RationalImpl n ) {
    51                 r{ n, (RationalImpl){1} };
    52         } // rational
    53 
    54         void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) {
    55                 RationalImpl t = simplify( n, d );                              // simplify
    56                 r.numerator = n / t;
    57                 r.denominator = d / t;
    58         } // rational
    59 
    60 
    61         // getter for numerator/denominator
    62 
    63         RationalImpl numerator( Rational(RationalImpl) r ) {
    64                 return r.numerator;
    65         } // numerator
    66 
    67         RationalImpl denominator( Rational(RationalImpl) r ) {
    68                 return r.denominator;
    69         } // denominator
    70 
    71         [ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src ) {
    72                 return dest = src.[ numerator, denominator ];
    73         } // ?=?
    74 
    75         // setter for numerator/denominator
    76 
    77         RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n ) {
    78                 RationalImpl prev = r.numerator;
    79                 RationalImpl t = gcd( abs( n ), r.denominator ); // simplify
    80                 r.numerator = n / t;
    81                 r.denominator = r.denominator / t;
    82                 return prev;
    83         } // numerator
    84 
    85         RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d ) {
    86                 RationalImpl prev = r.denominator;
    87                 RationalImpl t = simplify( r.numerator, d );    // simplify
    88                 r.numerator = r.numerator / t;
    89                 r.denominator = d / t;
    90                 return prev;
    91         } // denominator
    92 
    93         // comparison
    94 
    95         int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    96                 return l.numerator * r.denominator == l.denominator * r.numerator;
    97         } // ?==?
    98 
    99         int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    100                 return ! ( l == r );
    101         } // ?!=?
    102 
    103         int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    104                 return l.numerator * r.denominator < l.denominator * r.numerator;
    105         } // ?<?
    106 
    107         int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    108                 return l.numerator * r.denominator <= l.denominator * r.numerator;
    109         } // ?<=?
    110 
    111         int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    112                 return ! ( l <= r );
    113         } // ?>?
    114 
    115         int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    116                 return ! ( l < r );
    117         } // ?>=?
    118 
    119         // arithmetic
    120 
    121         Rational(RationalImpl) +?( Rational(RationalImpl) r ) {
    122                 Rational(RationalImpl) t = { r.numerator, r.denominator };
    123                 return t;
    124         } // +?
    125 
    126         Rational(RationalImpl) -?( Rational(RationalImpl) r ) {
    127                 Rational(RationalImpl) t = { -r.numerator, r.denominator };
    128                 return t;
    129         } // -?
    130 
    131         Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    132                 if ( l.denominator == r.denominator ) {                 // special case
    133                         Rational(RationalImpl) t = { l.numerator + r.numerator, l.denominator };
    134                         return t;
    135                 } else {
    136                         Rational(RationalImpl) t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
    137                         return t;
    138                 } // if
    139         } // ?+?
    140 
    141         Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    142                 if ( l.denominator == r.denominator ) {                 // special case
    143                         Rational(RationalImpl) t = { l.numerator - r.numerator, l.denominator };
    144                         return t;
    145                 } else {
    146                         Rational(RationalImpl) t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
    147                         return t;
    148                 } // if
    149         } // ?-?
    150 
    151         Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    152                 Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator };
    153                 return t;
    154         } // ?*?
    155 
    156         Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    157                 if ( r.numerator < (RationalImpl){0} ) {
    158                         r.numerator = -r.numerator;
    159                         r.denominator = -r.denominator;
    160                 } // if
    161                 Rational(RationalImpl) t = { l.numerator * r.denominator, l.denominator * r.numerator };
    162                 return t;
    163         } // ?/?
    164 
    165         // I/O
    166 
    167         forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    168         istype & ?|?( istype & is, Rational(RationalImpl) & r ) {
    169                 RationalImpl t;
    170                 is | r.numerator | r.denominator;
    171                 t = simplify( r.numerator, r.denominator );
    172                 r.numerator /= t;
    173                 r.denominator /= t;
    174                 return is;
    175         } // ?|?
    176 
    177         forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
    178         ostype & ?|?( ostype & os, Rational(RationalImpl ) r ) {
    179                 return os | r.numerator | '/' | r.denominator;
    180         } // ?|?
    181 } // distribution
     20// helper routines
     21
     22// Calculate greatest common denominator of two numbers, the first of which may be negative. Used to reduce rationals.
     23// alternative: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
     24forall( otype RationalImpl | arithmetic( RationalImpl ) )
     25static RationalImpl gcd( RationalImpl a, RationalImpl b ) {
     26        for ( ;; ) {                                                                            // Euclid's algorithm
     27                RationalImpl r = a % b;
     28          if ( r == (RationalImpl){0} ) break;
     29                a = b;
     30                b = r;
     31        } // for
     32        return b;
     33} // gcd
     34
     35forall( otype RationalImpl | arithmetic( RationalImpl ) )
     36static RationalImpl simplify( RationalImpl & n, RationalImpl & d ) {
     37        if ( d == (RationalImpl){0} ) {
     38                serr | "Invalid rational number construction: denominator cannot be equal to 0." | endl;
     39                exit( EXIT_FAILURE );
     40        } // exit
     41        if ( d < (RationalImpl){0} ) { d = -d; n = -n; }        // move sign to numerator
     42        return gcd( abs( n ), d );                                                      // simplify
     43} // Rationalnumber::simplify
     44
     45
     46// constructors
     47
     48forall( otype RationalImpl | arithmetic( RationalImpl ) )
     49void ?{}( Rational(RationalImpl) & r ) {
     50        r{ (RationalImpl){0}, (RationalImpl){1} };
     51} // rational
     52
     53forall( otype RationalImpl | arithmetic( RationalImpl ) )
     54void ?{}( Rational(RationalImpl) & r, RationalImpl n ) {
     55        r{ n, (RationalImpl){1} };
     56} // rational
     57
     58forall( otype RationalImpl | arithmetic( RationalImpl ) )
     59void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d ) {
     60        RationalImpl t = simplify( n, d );                                      // simplify
     61        r.numerator = n / t;
     62        r.denominator = d / t;
     63} // rational
     64
     65
     66// getter for numerator/denominator
     67
     68forall( otype RationalImpl | arithmetic( RationalImpl ) )
     69RationalImpl numerator( Rational(RationalImpl) r ) {
     70        return r.numerator;
     71} // numerator
     72
     73forall( otype RationalImpl | arithmetic( RationalImpl ) )
     74RationalImpl denominator( Rational(RationalImpl) r ) {
     75        return r.denominator;
     76} // denominator
     77
     78forall( otype RationalImpl | arithmetic( RationalImpl ) )
     79[ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src ) {
     80        return dest = src.[ numerator, denominator ];
     81}
     82
     83// setter for numerator/denominator
     84
     85forall( otype RationalImpl | arithmetic( RationalImpl ) )
     86RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n ) {
     87        RationalImpl prev = r.numerator;
     88        RationalImpl t = gcd( abs( n ), r.denominator );                // simplify
     89        r.numerator = n / t;
     90        r.denominator = r.denominator / t;
     91        return prev;
     92} // numerator
     93
     94forall( otype RationalImpl | arithmetic( RationalImpl ) )
     95RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d ) {
     96        RationalImpl prev = r.denominator;
     97        RationalImpl t = simplify( r.numerator, d );                    // simplify
     98        r.numerator = r.numerator / t;
     99        r.denominator = d / t;
     100        return prev;
     101} // denominator
     102
     103
     104// comparison
     105
     106forall( otype RationalImpl | arithmetic( RationalImpl ) )
     107int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     108        return l.numerator * r.denominator == l.denominator * r.numerator;
     109} // ?==?
     110
     111forall( otype RationalImpl | arithmetic( RationalImpl ) )
     112int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     113        return ! ( l == r );
     114} // ?!=?
     115
     116forall( otype RationalImpl | arithmetic( RationalImpl ) )
     117int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     118        return l.numerator * r.denominator < l.denominator * r.numerator;
     119} // ?<?
     120
     121forall( otype RationalImpl | arithmetic( RationalImpl ) )
     122int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     123        return l.numerator * r.denominator <= l.denominator * r.numerator;
     124} // ?<=?
     125
     126forall( otype RationalImpl | arithmetic( RationalImpl ) )
     127int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     128        return ! ( l <= r );
     129} // ?>?
     130
     131forall( otype RationalImpl | arithmetic( RationalImpl ) )
     132int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     133        return ! ( l < r );
     134} // ?>=?
     135
     136
     137// arithmetic
     138
     139forall( otype RationalImpl | arithmetic( RationalImpl ) )
     140Rational(RationalImpl) +?( Rational(RationalImpl) r ) {
     141        Rational(RationalImpl) t = { r.numerator, r.denominator };
     142        return t;
     143} // +?
     144
     145forall( otype RationalImpl | arithmetic( RationalImpl ) )
     146Rational(RationalImpl) -?( Rational(RationalImpl) r ) {
     147        Rational(RationalImpl) t = { -r.numerator, r.denominator };
     148        return t;
     149} // -?
     150
     151forall( otype RationalImpl | arithmetic( RationalImpl ) )
     152Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     153        if ( l.denominator == r.denominator ) {                         // special case
     154                Rational(RationalImpl) t = { l.numerator + r.numerator, l.denominator };
     155                return t;
     156        } else {
     157                Rational(RationalImpl) t = { l.numerator * r.denominator + l.denominator * r.numerator, l.denominator * r.denominator };
     158                return t;
     159        } // if
     160} // ?+?
     161
     162forall( otype RationalImpl | arithmetic( RationalImpl ) )
     163Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     164        if ( l.denominator == r.denominator ) {                         // special case
     165                Rational(RationalImpl) t = { l.numerator - r.numerator, l.denominator };
     166                return t;
     167        } else {
     168                Rational(RationalImpl) t = { l.numerator * r.denominator - l.denominator * r.numerator, l.denominator * r.denominator };
     169                return t;
     170        } // if
     171} // ?-?
     172
     173forall( otype RationalImpl | arithmetic( RationalImpl ) )
     174Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     175        Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator };
     176        return t;
     177} // ?*?
     178
     179forall( otype RationalImpl | arithmetic( RationalImpl ) )
     180Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
     181        if ( r.numerator < (RationalImpl){0} ) {
     182                r.numerator = -r.numerator;
     183                r.denominator = -r.denominator;
     184        } // if
     185        Rational(RationalImpl) t = { l.numerator * r.denominator, l.denominator * r.numerator };
     186        return t;
     187} // ?/?
     188
    182189
    183190// conversion
     
    188195} // widen
    189196
     197// http://www.ics.uci.edu/~eppstein/numth/frap.c
    190198forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); RationalImpl convert( double ); } )
    191199Rational(RationalImpl) narrow( double f, RationalImpl md ) {
    192         // http://www.ics.uci.edu/~eppstein/numth/frap.c
    193200        if ( md <= (RationalImpl){1} ) {                                        // maximum fractional digits too small?
    194201                return (Rational(RationalImpl)){ convert( f ), (RationalImpl){1}}; // truncate fraction
     
    217224} // narrow
    218225
     226
     227// I/O
     228
     229forall( otype RationalImpl | arithmetic( RationalImpl ) )
     230forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
     231istype & ?|?( istype & is, Rational(RationalImpl) & r ) {
     232        RationalImpl t;
     233        is | r.numerator | r.denominator;
     234        t = simplify( r.numerator, r.denominator );
     235        r.numerator /= t;
     236        r.denominator /= t;
     237        return is;
     238} // ?|?
     239
     240forall( otype RationalImpl | arithmetic( RationalImpl ) )
     241forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
     242ostype & ?|?( ostype & os, Rational(RationalImpl ) r ) {
     243        return os | r.numerator | '/' | r.denominator;
     244} // ?|?
     245
    219246// Local Variables: //
    220247// tab-width: 4 //
  • src/libcfa/stdhdr/assert.h

    rb21c77a r97397a26  
    3333        #define verify(x) assert(x)
    3434        #define verifyf(x, ...) assertf(x, __VA_ARGS__)
    35         #define __CFA_WITH_VERIFY__
    3635#else
    3736        #define verify(x)
  • src/libcfa/stdlib

    rb21c77a r97397a26  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  2 08:46:35 2018
    13 // Update Count     : 306
     12// Last Modified On : Wed May 16 07:53:10 2018
     13// Update Count     : 300
    1414//
    1515
    1616#pragma once
    1717
    18 #include <stdlib.h>                                                                             // allocation, strto*, *abs
    19 extern "C" {
    20         void * memalign( size_t align, size_t size );
    21         void * aligned_alloc( size_t align, size_t size );
    22         void * memset( void * dest, int c, size_t size );
    23 } // extern "C"
     18#include <stdlib.h>                                                                             // strto*, *abs
    2419
    2520//---------------------------------------
     
    3227//---------------------------------------
    3328
     29// C dynamic allocation
    3430static inline forall( dtype T | sized(T) ) {
    35         // C dynamic allocation
    36 
    3731        T * malloc( void ) {
    3832                // printf( "* malloc\n" );
     
    5751        } // realloc
    5852
     53        extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void *
    5954        T * memalign( size_t align ) {
    6055                //printf( "X4\n" );
     
    6257        } // memalign
    6358
     59        extern "C" { void * aligned_alloc( size_t align, size_t size ); } // use default C routine for void *
    6460        T * aligned_alloc( size_t align ) {
    6561                //printf( "X5\n" );
     
    7470
    7571        // Cforall dynamic allocation
     72        extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void *
    7673
    7774        T * alloc( void ) {
     
    106103forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    107104
    108 
    109 static inline forall( dtype T | sized(T) ) {
    110         T * align_alloc( size_t align ) {
    111                 //printf( "X13\n" );
    112                 return (T *)memalign( align, sizeof(T) );
    113         } // align_alloc
    114 
    115         T * align_alloc( size_t align, char fill ) {
    116                 //printf( "X14\n" );
    117                 T * ptr = (T *)memalign( align, sizeof(T) );
    118                 return (T *)memset( ptr, (int)fill, sizeof(T) );
    119         } // align_alloc
    120 
    121         T * align_alloc( size_t align, size_t dim ) {
    122                 //printf( "X15\n" );
    123                 return (T *)memalign( align, dim * sizeof(T) );
    124         } // align_alloc
    125 
    126         T * align_alloc( size_t align, size_t dim, char fill ) {
    127                 //printf( "X16\n" );
    128                 T * ptr = (T *)memalign( align, dim * sizeof(T) );
    129                 return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
    130         } // align_alloc
    131 } // distribution
    132 
    133 
    134 static inline forall( dtype T | sized(T) ) {
    135         // data, non-array types
    136 
    137         T * memset( T * dest, char c ) {
    138                 //printf( "X17\n" );
    139                 return (T *)memset( dest, c, sizeof(T) );
    140         } // memset
    141 
    142         extern "C" { void * memcpy( void * dest, const void * src, size_t size ); } // use default C routine for void *
    143 
    144         T * memcpy( T * dest, const T * src ) {
    145                 //printf( "X18\n" );
    146                 return (T *)memcpy( dest, src, sizeof(T) );
    147         } // memcpy
    148 } // distribution
    149 
    150 static inline forall( dtype T | sized(T) ) {
    151         // data, array types
    152 
    153         T * memset( T dest[], size_t dim, char c ) {
    154                 //printf( "X19\n" );
    155                 return (T *)(void *)memset( dest, c, dim * sizeof(T) ); // C memset
    156         } // memset
    157 
    158         T * memcpy( T dest[], const T src[], size_t dim ) {
    159                 //printf( "X20\n" );
    160                 return (T *)(void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy
    161         } // memcpy
    162 } // distribution
     105static inline forall( dtype T | sized(T) ) T * align_alloc( size_t align ) {
     106        //printf( "X13\n" );
     107        return (T *)memalign( align, sizeof(T) );
     108} // align_alloc
     109static inline forall( dtype T | sized(T) ) T * align_alloc( size_t align, char fill ) {
     110        //printf( "X14\n" );
     111    T * ptr = (T *)memalign( align, sizeof(T) );
     112    return (T *)memset( ptr, (int)fill, sizeof(T) );
     113} // align_alloc
     114
     115static inline forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim ) {
     116        //printf( "X15\n" );
     117        return (T *)memalign( align, dim * sizeof(T) );
     118} // align_alloc
     119static inline forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim, char fill ) {
     120        //printf( "X16\n" );
     121    T * ptr = (T *)memalign( align, dim * sizeof(T) );
     122    return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
     123} // align_alloc
     124
     125
     126// data, non-array types
     127static inline forall( dtype T | sized(T) ) T * memset( T * dest, char c ) {
     128        //printf( "X17\n" );
     129        return (T *)memset( dest, c, sizeof(T) );
     130} // memset
     131extern "C" { void * memcpy( void * dest, const void * src, size_t size ); } // use default C routine for void *
     132static inline forall( dtype T | sized(T) ) T * memcpy( T * dest, const T * src ) {
     133        //printf( "X18\n" );
     134        return (T *)memcpy( dest, src, sizeof(T) );
     135} // memcpy
     136
     137// data, array types
     138static inline forall( dtype T | sized(T) ) T * memset( T dest[], size_t dim, char c ) {
     139        //printf( "X19\n" );
     140        return (T *)(void *)memset( dest, c, dim * sizeof(T) ); // C memset
     141} // memset
     142static inline forall( dtype T | sized(T) ) T * memcpy( T dest[], const T src[], size_t dim ) {
     143        //printf( "X20\n" );
     144        return (T *)(void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy
     145} // memcpy
    163146
    164147// allocation/deallocation and constructor/destructor, non-array types
     
    206189//---------------------------------------
    207190
    208 forall( otype E | { int ?<?( E, E ); } ) {
    209         E * bsearch( E key, const E * vals, size_t dim );
    210         size_t bsearch( E key, const E * vals, size_t dim );
    211         E * bsearchl( E key, const E * vals, size_t dim );
    212         size_t bsearchl( E key, const E * vals, size_t dim );
    213         E * bsearchu( E key, const E * vals, size_t dim );
    214         size_t bsearchu( E key, const E * vals, size_t dim );
    215 
    216         void qsort( E * vals, size_t dim );
    217 } // distribution
    218 
    219 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {
    220         E * bsearch( K key, const E * vals, size_t dim );
    221         size_t bsearch( K key, const E * vals, size_t dim );
    222         E * bsearchl( K key, const E * vals, size_t dim );
    223         size_t bsearchl( K key, const E * vals, size_t dim );
    224         E * bsearchu( K key, const E * vals, size_t dim );
    225         size_t bsearchu( K key, const E * vals, size_t dim );
    226 } // distribution
     191forall( otype E | { int ?<?( E, E ); } )
     192E * bsearch( E key, const E * vals, size_t dim );
     193
     194forall( otype E | { int ?<?( E, E ); } )
     195size_t bsearch( E key, const E * vals, size_t dim );
     196
     197forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     198E * bsearch( K key, const E * vals, size_t dim );
     199
     200forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     201size_t bsearch( K key, const E * vals, size_t dim );
     202
     203
     204forall( otype E | { int ?<?( E, E ); } )
     205E * bsearchl( E key, const E * vals, size_t dim );
     206
     207forall( otype E | { int ?<?( E, E ); } )
     208size_t bsearchl( E key, const E * vals, size_t dim );
     209
     210forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     211E * bsearchl( K key, const E * vals, size_t dim );
     212
     213forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     214size_t bsearchl( K key, const E * vals, size_t dim );
     215
     216
     217forall( otype E | { int ?<?( E, E ); } )
     218E * bsearchu( E key, const E * vals, size_t dim );
     219
     220forall( otype E | { int ?<?( E, E ); } )
     221size_t bsearchu( E key, const E * vals, size_t dim );
     222
     223forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     224E * bsearchu( K key, const E * vals, size_t dim );
     225
     226forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     227size_t bsearchu( K key, const E * vals, size_t dim );
     228
     229
     230forall( otype E | { int ?<?( E, E ); } )
     231void qsort( E * vals, size_t dim );
    227232
    228233//---------------------------------------
  • src/libcfa/stdlib.c

    rb21c77a r97397a26  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  2 06:15:05 2018
    13 // Update Count     : 448
     12// Last Modified On : Wed Jan  3 08:29:29 2018
     13// Update Count     : 444
    1414//
    1515
     
    130130//---------------------------------------
    131131
    132 forall( otype E | { int ?<?( E, E ); } ) {
    133         E * bsearch( E key, const E * vals, size_t dim ) {
    134                 int cmp( const void * t1, const void * t2 ) {
    135                         return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
    136                 } // cmp
    137                 return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
    138         } // bsearch
    139 
    140         size_t bsearch( E key, const E * vals, size_t dim ) {
    141                 E * result = bsearch( key, vals, dim );
    142                 return result ? result - vals : dim;                    // pointer subtraction includes sizeof(E)
    143         } // bsearch
    144 
    145         size_t bsearchl( E key, const E * vals, size_t dim ) {
    146                 size_t l = 0, m, h = dim;
    147                 while ( l < h ) {
    148                         m = (l + h) / 2;
    149                         if ( (E &)(vals[m]) < key ) {                           // cast away const
    150                                 l = m + 1;
    151                         } else {
    152                                 h = m;
    153                         } // if
    154                 } // while
    155                 return l;
    156         } // bsearchl
    157 
    158         E * bsearchl( E key, const E * vals, size_t dim ) {
    159                 size_t posn = bsearchl( key, vals, dim );
    160                 return (E *)(&vals[posn]);                                              // cast away const
    161         } // bsearchl
    162 
    163         size_t bsearchu( E key, const E * vals, size_t dim ) {
    164                 size_t l = 0, m, h = dim;
    165                 while ( l < h ) {
    166                         m = (l + h) / 2;
    167                         if ( ! ( key < (E &)(vals[m]) ) ) {                     // cast away const
    168                                 l = m + 1;
    169                         } else {
    170                                 h = m;
    171                         } // if
    172                 } // while
    173                 return l;
    174         } // bsearchu
    175 
    176         E * bsearchu( E key, const E * vals, size_t dim ) {
    177                 size_t posn = bsearchu( key, vals, dim );
    178                 return (E *)(&vals[posn]);
    179         } // bsearchu
    180 
    181 
    182         void qsort( E * vals, size_t dim ) {
    183                 int cmp( const void * t1, const void * t2 ) {
    184                         return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
    185                 } // cmp
    186                 qsort( vals, dim, sizeof(E), cmp );
    187         } // qsort
    188 } // distribution
    189 
    190 
    191 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {
    192         E * bsearch( K key, const E * vals, size_t dim ) {
    193                 int cmp( const void * t1, const void * t2 ) {
    194                         return *(K *)t1 < getKey( *(E *)t2 ) ? -1 : getKey( *(E *)t2 ) < *(K *)t1 ? 1 : 0;
    195                 } // cmp
    196                 return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
    197         } // bsearch
    198 
    199         size_t bsearch( K key, const E * vals, size_t dim ) {
    200                 E * result = bsearch( key, vals, dim );
    201                 return result ? result - vals : dim;                    // pointer subtraction includes sizeof(E)
    202         } // bsearch
    203 
    204         size_t bsearchl( K key, const E * vals, size_t dim ) {
    205                 size_t l = 0, m, h = dim;
    206                 while ( l < h ) {
    207                         m = (l + h) / 2;
    208                         if ( getKey( vals[m] ) < key ) {
    209                                 l = m + 1;
    210                         } else {
    211                                 h = m;
    212                         } // if
    213                 } // while
    214                 return l;
    215         } // bsearchl
    216 
    217         E * bsearchl( K key, const E * vals, size_t dim ) {
    218                 size_t posn = bsearchl( key, vals, dim );
    219                 return (E *)(&vals[posn]);                                              // cast away const
    220         } // bsearchl
    221 
    222         size_t bsearchu( K key, const E * vals, size_t dim ) {
    223                 size_t l = 0, m, h = dim;
    224                 while ( l < h ) {
    225                         m = (l + h) / 2;
    226                         if ( ! ( key < getKey( vals[m] ) ) ) {
    227                                 l = m + 1;
    228                         } else {
    229                                 h = m;
    230                         } // if
    231                 } // while
    232                 return l;
    233         } // bsearchu
    234 
    235         E * bsearchu( K key, const E * vals, size_t dim ) {
    236                 size_t posn = bsearchu( key, vals, dim );
    237                 return (E *)(&vals[posn]);
    238         } // bsearchu
    239 } // distribution
     132forall( otype E | { int ?<?( E, E ); } )
     133E * bsearch( E key, const E * vals, size_t dim ) {
     134        int cmp( const void * t1, const void * t2 ) {
     135                return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
     136        } // cmp
     137        return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
     138} // bsearch
     139
     140forall( otype E | { int ?<?( E, E ); } )
     141size_t bsearch( E key, const E * vals, size_t dim ) {
     142        E * result = bsearch( key, vals, dim );
     143        return result ? result - vals : dim;                            // pointer subtraction includes sizeof(E)
     144} // bsearch
     145
     146forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     147E * bsearch( K key, const E * vals, size_t dim ) {
     148        int cmp( const void * t1, const void * t2 ) {
     149                return *(K *)t1 < getKey( *(E *)t2 ) ? -1 : getKey( *(E *)t2 ) < *(K *)t1 ? 1 : 0;
     150        } // cmp
     151        return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
     152} // bsearch
     153
     154forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     155size_t bsearch( K key, const E * vals, size_t dim ) {
     156        E * result = bsearch( key, vals, dim );
     157        return result ? result - vals : dim;                            // pointer subtraction includes sizeof(E)
     158} // bsearch
     159
     160
     161forall( otype E | { int ?<?( E, E ); } )
     162size_t bsearchl( E key, const E * vals, size_t dim ) {
     163        size_t l = 0, m, h = dim;
     164        while ( l < h ) {
     165                m = (l + h) / 2;
     166                if ( (E &)(vals[m]) < key ) {                                   // cast away const
     167                        l = m + 1;
     168                } else {
     169                        h = m;
     170                } // if
     171        } // while
     172        return l;
     173} // bsearchl
     174
     175forall( otype E | { int ?<?( E, E ); } )
     176E * bsearchl( E key, const E * vals, size_t dim ) {
     177        size_t posn = bsearchl( key, vals, dim );
     178        return (E *)(&vals[posn]);                                                      // cast away const
     179} // bsearchl
     180
     181forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     182size_t bsearchl( K key, const E * vals, size_t dim ) {
     183        size_t l = 0, m, h = dim;
     184        while ( l < h ) {
     185                m = (l + h) / 2;
     186                if ( getKey( vals[m] ) < key ) {
     187                        l = m + 1;
     188                } else {
     189                        h = m;
     190                } // if
     191        } // while
     192        return l;
     193} // bsearchl
     194
     195forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     196E * bsearchl( K key, const E * vals, size_t dim ) {
     197        size_t posn = bsearchl( key, vals, dim );
     198        return (E *)(&vals[posn]);                                                      // cast away const
     199} // bsearchl
     200
     201
     202forall( otype E | { int ?<?( E, E ); } )
     203size_t bsearchu( E key, const E * vals, size_t dim ) {
     204        size_t l = 0, m, h = dim;
     205        while ( l < h ) {
     206                m = (l + h) / 2;
     207                if ( ! ( key < (E &)(vals[m]) ) ) {                             // cast away const
     208                        l = m + 1;
     209                } else {
     210                        h = m;
     211                } // if
     212        } // while
     213        return l;
     214} // bsearchu
     215
     216forall( otype E | { int ?<?( E, E ); } )
     217E * bsearchu( E key, const E * vals, size_t dim ) {
     218        size_t posn = bsearchu( key, vals, dim );
     219        return (E *)(&vals[posn]);
     220} // bsearchu
     221
     222forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     223size_t bsearchu( K key, const E * vals, size_t dim ) {
     224        size_t l = 0, m, h = dim;
     225        while ( l < h ) {
     226                m = (l + h) / 2;
     227                if ( ! ( key < getKey( vals[m] ) ) ) {
     228                        l = m + 1;
     229                } else {
     230                        h = m;
     231                } // if
     232        } // while
     233        return l;
     234} // bsearchu
     235
     236forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
     237E * bsearchu( K key, const E * vals, size_t dim ) {
     238        size_t posn = bsearchu( key, vals, dim );
     239        return (E *)(&vals[posn]);
     240} // bsearchu
     241
     242
     243forall( otype E | { int ?<?( E, E ); } )
     244void qsort( E * vals, size_t dim ) {
     245        int cmp( const void * t1, const void * t2 ) {
     246                return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
     247        } // cmp
     248        qsort( vals, dim, sizeof(E), cmp );
     249} // qsort
    240250
    241251//---------------------------------------
  • src/main.cc

    rb21c77a r97397a26  
    1111// Created On       : Fri May 15 23:12:02 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Wed Jun  6 15:51:47 2018
    14 // Update Count     : 498
     13// Last Modified On : Mon May  7 14:35:57 2018
     14// Update Count     : 492
    1515//
    1616
     
    160160                 << "." << endl;
    161161        backtrace( 2 );                                                                         // skip first 2 stack frames
    162         //_exit( EXIT_FAILURE );
    163         abort();
     162        exit( EXIT_FAILURE );
    164163} // sigSegvBusHandler
    165164
     
    262261                } // if
    263262
    264                 PASS( "fixLabels", ControlStruct::fixLabels( translationUnit ) );
     263                PASS( "mutate", ControlStruct::mutate( translationUnit ) );
    265264                PASS( "fixNames", CodeGen::fixNames( translationUnit ) );
    266265                PASS( "genInit", InitTweak::genInit( translationUnit ) );
     
    572571        yyin = input;
    573572        yylineno = 1;
     573        typedefTable.enterScope();
    574574        int parseStatus = yyparse();
    575575
  • src/prelude/Makefile.am

    rb21c77a r97397a26  
    3737# create forward declarations for gcc builtins
    3838gcc-builtins.cf : gcc-builtins.c prototypes.sed
    39         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E -P $< | sed -r -f prototypes.sed > $@
     39        ${AM_V_GEN}@BACKEND_CC@ -E -P $< | sed -r -f prototypes.sed > $@
    4040
    4141gcc-builtins.c : builtins.def prototypes.awk sync-builtins.cf
    42         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E prototypes.c | awk -f prototypes.awk > $@
     42        ${AM_V_GEN}@BACKEND_CC@ -E prototypes.c | awk -f prototypes.awk > $@
    4343
    4444builtins.def :
  • src/prelude/Makefile.in

    rb21c77a r97397a26  
    506506# create forward declarations for gcc builtins
    507507gcc-builtins.cf : gcc-builtins.c prototypes.sed
    508         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E -P $< | sed -r -f prototypes.sed > $@
     508        ${AM_V_GEN}@BACKEND_CC@ -E -P $< | sed -r -f prototypes.sed > $@
    509509
    510510gcc-builtins.c : builtins.def prototypes.awk sync-builtins.cf
    511         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -E prototypes.c | awk -f prototypes.awk > $@
     511        ${AM_V_GEN}@BACKEND_CC@ -E prototypes.c | awk -f prototypes.awk > $@
    512512
    513513builtins.def :
  • src/prelude/extras.regx

    rb21c77a r97397a26  
    11typedef.* size_t;
    22typedef.* ptrdiff_t;
    3 typedef.* __int8_t;
    4 typedef.* __int16_t;
    5 typedef.* __int32_t;
    6 typedef.* __int64_t;
    7 typedef.* __uint8_t;
    8 typedef.* __uint16_t;
    9 typedef.* __uint32_t;
    10 typedef.* __uint64_t;
    113typedef.* int8_t;
    124typedef.* int16_t;
  • src/prelude/prelude.cf

    rb21c77a r97397a26  
    458458signed long long int    ?=?( signed long long int &, signed long long int ),    ?=?( volatile signed long long int &, signed long long int );
    459459unsigned long long int  ?=?( unsigned long long int &, unsigned long long int ), ?=?( volatile unsigned long long int &, unsigned long long int );
     460__int128        ?=?( __int128 &, __int128 ),    ?=?( volatile __int128 &, __int128 );
    460461zero_t                  ?=?( zero_t &, zero_t );
    461462one_t                   ?=?( one_t &, one_t );
  • src/prelude/sync-builtins.cf

    rb21c77a r97397a26  
    77long long int __sync_fetch_and_add(volatile long long int *, long long int,...);
    88long long int __sync_fetch_and_add_8(volatile long long int *, long long int,...);
    9 #if defined(__SIZEOF_INT128__)
    109__int128 __sync_fetch_and_add(volatile __int128 *, __int128,...);
    1110__int128 __sync_fetch_and_add_16(volatile __int128 *, __int128,...);
    12 #endif
    1311
    1412char __sync_fetch_and_sub(volatile char *, char,...);
     
    2018long long int __sync_fetch_and_sub(volatile long long int *, long long int,...);
    2119long long int __sync_fetch_and_sub_8(volatile long long int *, long long int,...);
    22 #if defined(__SIZEOF_INT128__)
    2320__int128 __sync_fetch_and_sub(volatile __int128 *, __int128,...);
    2421__int128 __sync_fetch_and_sub_16(volatile __int128 *, __int128,...);
    25 #endif
    2622
    2723char __sync_fetch_and_or(volatile char *, char,...);
     
    3329long long int __sync_fetch_and_or(volatile long long int *, long long int,...);
    3430long long int __sync_fetch_and_or_8(volatile long long int *, long long int,...);
    35 #if defined(__SIZEOF_INT128__)
    3631__int128 __sync_fetch_and_or(volatile __int128 *, __int128,...);
    3732__int128 __sync_fetch_and_or_16(volatile __int128 *, __int128,...);
    38 #endif
    3933
    4034char __sync_fetch_and_and(volatile char *, char,...);
     
    4640long long int __sync_fetch_and_and(volatile long long int *, long long int,...);
    4741long long int __sync_fetch_and_and_8(volatile long long int *, long long int,...);
    48 #if defined(__SIZEOF_INT128__)
    4942__int128 __sync_fetch_and_and(volatile __int128 *, __int128,...);
    5043__int128 __sync_fetch_and_and_16(volatile __int128 *, __int128,...);
    51 #endif
    5244
    5345char __sync_fetch_and_xor(volatile char *, char,...);
     
    5951long long int __sync_fetch_and_xor(volatile long long int *, long long int,...);
    6052long long int __sync_fetch_and_xor_8(volatile long long int *, long long int,...);
    61 #if defined(__SIZEOF_INT128__)
    6253__int128 __sync_fetch_and_xor(volatile __int128 *, __int128,...);
    6354__int128 __sync_fetch_and_xor_16(volatile __int128 *, __int128,...);
    64 #endif
    6555
    6656char __sync_fetch_and_nand(volatile char *, char,...);
     
    7262long long int __sync_fetch_and_nand(volatile long long int *, long long int,...);
    7363long long int __sync_fetch_and_nand_8(volatile long long int *, long long int,...);
    74 #if defined(__SIZEOF_INT128__)
    7564__int128 __sync_fetch_and_nand(volatile __int128 *, __int128,...);
    7665__int128 __sync_fetch_and_nand_16(volatile __int128 *, __int128,...);
    77 #endif
    7866
    7967char __sync_add_and_fetch(volatile char *, char,...);
     
    8573long long int __sync_add_and_fetch(volatile long long int *, long long int,...);
    8674long long int __sync_add_and_fetch_8(volatile long long int *, long long int,...);
    87 #if defined(__SIZEOF_INT128__)
    8875__int128 __sync_add_and_fetch(volatile __int128 *, __int128,...);
    8976__int128 __sync_add_and_fetch_16(volatile __int128 *, __int128,...);
    90 #endif
    9177
    9278char __sync_sub_and_fetch(volatile char *, char,...);
     
    9884long long int __sync_sub_and_fetch(volatile long long int *, long long int,...);
    9985long long int __sync_sub_and_fetch_8(volatile long long int *, long long int,...);
    100 #if defined(__SIZEOF_INT128__)
    10186__int128 __sync_sub_and_fetch(volatile __int128 *, __int128,...);
    10287__int128 __sync_sub_and_fetch_16(volatile __int128 *, __int128,...);
    103 #endif
    10488
    10589char __sync_or_and_fetch(volatile char *, char,...);
     
    11195long long int __sync_or_and_fetch(volatile long long int *, long long int,...);
    11296long long int __sync_or_and_fetch_8(volatile long long int *, long long int,...);
    113 #if defined(__SIZEOF_INT128__)
    11497__int128 __sync_or_and_fetch(volatile __int128 *, __int128,...);
    11598__int128 __sync_or_and_fetch_16(volatile __int128 *, __int128,...);
    116 #endif
    11799
    118100char __sync_and_and_fetch(volatile char *, char,...);
     
    124106long long int __sync_and_and_fetch(volatile long long int *, long long int,...);
    125107long long int __sync_and_and_fetch_8(volatile long long int *, long long int,...);
    126 #if defined(__SIZEOF_INT128__)
    127108__int128 __sync_and_and_fetch(volatile __int128 *, __int128,...);
    128109__int128 __sync_and_and_fetch_16(volatile __int128 *, __int128,...);
    129 #endif
    130110
    131111char __sync_xor_and_fetch(volatile char *, char,...);
     
    137117long long int __sync_xor_and_fetch(volatile long long int *, long long int,...);
    138118long long int __sync_xor_and_fetch_8(volatile long long int *, long long int,...);
    139 #if defined(__SIZEOF_INT128__)
    140119__int128 __sync_xor_and_fetch(volatile __int128 *, __int128,...);
    141120__int128 __sync_xor_and_fetch_16(volatile __int128 *, __int128,...);
    142 #endif
    143121
    144122char __sync_nand_and_fetch(volatile char *, char,...);
     
    150128long long int __sync_nand_and_fetch(volatile long long int *, long long int,...);
    151129long long int __sync_nand_and_fetch_8(volatile long long int *, long long int,...);
    152 #if defined(__SIZEOF_INT128__)
    153130__int128 __sync_nand_and_fetch(volatile __int128 *, __int128,...);
    154131__int128 __sync_nand_and_fetch_16(volatile __int128 *, __int128,...);
    155 #endif
    156132
    157133_Bool __sync_bool_compare_and_swap(volatile char *, char, char,...);
     
    163139_Bool __sync_bool_compare_and_swap(volatile long long int *, long long int, long long int,...);
    164140_Bool __sync_bool_compare_and_swap_8(volatile long long int *, long long int, long long int,...);
    165 #if defined(__SIZEOF_INT128__)
    166141_Bool __sync_bool_compare_and_swap(volatile __int128 *, __int128, __int128,...);
    167142_Bool __sync_bool_compare_and_swap_16(volatile __int128 *, __int128, __int128,...);
    168 #endif
    169143
    170144char __sync_val_compare_and_swap(volatile char *, char, char,...);
     
    176150long long int __sync_val_compare_and_swap(volatile long long int *, long long int, long long int,...);
    177151long long int __sync_val_compare_and_swap_8(volatile long long int *, long long int, long long int,...);
    178 #if defined(__SIZEOF_INT128__)
    179152__int128 __sync_val_compare_and_swap(volatile __int128 *, __int128, __int128,...);
    180153__int128 __sync_val_compare_and_swap_16(volatile __int128 *, __int128, __int128,...);
    181 #endif
    182154
    183155char __sync_lock_test_and_set(volatile char *, char,...);
     
    189161long long int __sync_lock_test_and_set(volatile long long int *, long long int,...);
    190162long long int __sync_lock_test_and_set_8(volatile long long int *, long long int,...);
    191 #if defined(__SIZEOF_INT128__)
    192163__int128 __sync_lock_test_and_set(volatile __int128 *, __int128,...);
    193164__int128 __sync_lock_test_and_set_16(volatile __int128 *, __int128,...);
    194 #endif
    195165
    196166void __sync_lock_release(volatile char *,...);
     
    202172void __sync_lock_release(volatile long long int *,...);
    203173void __sync_lock_release_8(volatile long long int *,...);
    204 #if defined(__SIZEOF_INT128__)
    205174void __sync_lock_release(volatile __int128 *,...);
    206175void __sync_lock_release_16(volatile __int128 *,...);
    207 #endif
    208176
    209177void __sync_synchronize();
     
    217185_Bool __atomic_test_and_set(volatile int *, int);
    218186_Bool __atomic_test_and_set(volatile long long int *, int);
    219 #if defined(__SIZEOF_INT128__)
    220187_Bool __atomic_test_and_set(volatile __int128 *, int);
    221 #endif
    222 
    223188void __atomic_clear(volatile _Bool *, int);
    224189void __atomic_clear(volatile char *, int);
     
    226191void __atomic_clear(volatile int *, int);
    227192void __atomic_clear(volatile long long int *, int);
    228 #if defined(__SIZEOF_INT128__)
    229193void __atomic_clear(volatile __int128 *, int);
    230 #endif
    231194
    232195char __atomic_exchange_n(volatile char *, volatile char *, int);
     
    242205long long int __atomic_exchange_8(volatile long long int *, long long int, int);
    243206void __atomic_exchange(volatile long long int *, volatile long long int *, volatile long long int *, int);
    244 #if defined(__SIZEOF_INT128__)
    245207__int128 __atomic_exchange_n(volatile __int128 *, volatile __int128 *, int);
    246208__int128 __atomic_exchange_16(volatile __int128 *, __int128, int);
    247209void __atomic_exchange(volatile __int128 *, volatile __int128 *, volatile __int128 *, int);
    248 #endif
    249 
    250 _Bool __atomic_load_n(const volatile _Bool *, int);
    251 void __atomic_load(const volatile _Bool *, volatile _Bool *, int);
     210
    252211char __atomic_load_n(const volatile char *, int);
    253212char __atomic_load_1(const volatile char *, int);
     
    262221long long int __atomic_load_8(const volatile long long int *, int);
    263222void __atomic_load(const volatile long long int *, volatile long long int *, int);
    264 #if defined(__SIZEOF_INT128__)
    265223__int128 __atomic_load_n(const volatile __int128 *, int);
    266224__int128 __atomic_load_16(const volatile __int128 *, int);
    267225void __atomic_load(const volatile __int128 *, volatile __int128 *, int);
    268 #endif
    269226
    270227_Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int);
     
    280237_Bool __atomic_compare_exchange_8(volatile long long int *, long long int *, long long int, _Bool, int, int);
    281238_Bool __atomic_compare_exchange  (volatile long long int *, long long int *, long long int *, _Bool, int, int);
    282 #if defined(__SIZEOF_INT128__)
    283239_Bool __atomic_compare_exchange_n (volatile __int128 *, __int128 *, __int128, _Bool, int, int);
    284240_Bool __atomic_compare_exchange_16(volatile __int128 *, __int128 *, __int128, _Bool, int, int);
    285241_Bool __atomic_compare_exchange   (volatile __int128 *, __int128 *, __int128 *, _Bool, int, int);
    286 #endif
    287242
    288243void __atomic_store_n(volatile _Bool *, _Bool, int);
     244void __atomic_store_1(volatile _Bool *, _Bool, int);
    289245void __atomic_store(volatile _Bool *, _Bool *, int);
    290246void __atomic_store_n(volatile char *, char, int);
     
    300256void __atomic_store_8(volatile long long int *, long long int, int);
    301257void __atomic_store(volatile long long int *, long long int *, int);
    302 #if defined(__SIZEOF_INT128__)
    303258void __atomic_store_n(volatile __int128 *, __int128, int);
    304259void __atomic_store_16(volatile __int128 *, __int128, int);
    305260void __atomic_store(volatile __int128 *, __int128 *, int);
    306 #endif
    307261
    308262char __atomic_add_fetch  (volatile char *, char, int);
     
    314268long long int __atomic_add_fetch  (volatile long long int *, long long int, int);
    315269long long int __atomic_add_fetch_8(volatile long long int *, long long int, int);
    316 #if defined(__SIZEOF_INT128__)
    317270__int128 __atomic_add_fetch   (volatile __int128 *, __int128, int);
    318271__int128 __atomic_add_fetch_16(volatile __int128 *, __int128, int);
    319 #endif
    320272
    321273char __atomic_sub_fetch  (volatile char *, char, int);
     
    327279long long int __atomic_sub_fetch  (volatile long long int *, long long int, int);
    328280long long int __atomic_sub_fetch_8(volatile long long int *, long long int, int);
    329 #if defined(__SIZEOF_INT128__)
    330281__int128 __atomic_sub_fetch   (volatile __int128 *, __int128, int);
    331282__int128 __atomic_sub_fetch_16(volatile __int128 *, __int128, int);
    332 #endif
    333283
    334284char __atomic_and_fetch  (volatile char *, char, int);
     
    340290long long int __atomic_and_fetch  (volatile long long int *, long long int, int);
    341291long long int __atomic_and_fetch_8(volatile long long int *, long long int, int);
    342 #if defined(__SIZEOF_INT128__)
    343292__int128 __atomic_and_fetch   (volatile __int128 *, __int128, int);
    344293__int128 __atomic_and_fetch_16(volatile __int128 *, __int128, int);
    345 #endif
    346294
    347295char __atomic_nand_fetch  (volatile char *, char, int);
     
    353301long long int __atomic_nand_fetch  (volatile long long int *, long long int, int);
    354302long long int __atomic_nand_fetch_8(volatile long long int *, long long int, int);
    355 #if defined(__SIZEOF_INT128__)
    356303__int128 __atomic_nand_fetch   (volatile __int128 *, __int128, int);
    357304__int128 __atomic_nand_fetch_16(volatile __int128 *, __int128, int);
    358 #endif
    359305
    360306char __atomic_xor_fetch  (volatile char *, char, int);
     
    366312long long int __atomic_xor_fetch  (volatile long long int *, long long int, int);
    367313long long int __atomic_xor_fetch_8(volatile long long int *, long long int, int);
    368 #if defined(__SIZEOF_INT128__)
    369314__int128 __atomic_xor_fetch   (volatile __int128 *, __int128, int);
    370315__int128 __atomic_xor_fetch_16(volatile __int128 *, __int128, int);
    371 #endif
    372316
    373317char __atomic_or_fetch  (volatile char *, char, int);
     
    379323long long int __atomic_or_fetch  (volatile long long int *, long long int, int);
    380324long long int __atomic_or_fetch_8(volatile long long int *, long long int, int);
    381 #if defined(__SIZEOF_INT128__)
    382325__int128 __atomic_or_fetch   (volatile __int128 *, __int128, int);
    383326__int128 __atomic_or_fetch_16(volatile __int128 *, __int128, int);
    384 #endif
    385327
    386328char __atomic_fetch_add  (volatile char *, char, int);
     
    392334long long int __atomic_fetch_add  (volatile long long int *, long long int, int);
    393335long long int __atomic_fetch_add_8(volatile long long int *, long long int, int);
    394 #if defined(__SIZEOF_INT128__)
    395336__int128 __atomic_fetch_add   (volatile __int128 *, __int128, int);
    396337__int128 __atomic_fetch_add_16(volatile __int128 *, __int128, int);
    397 #endif
    398338
    399339char __atomic_fetch_sub  (volatile char *, char, int);
     
    405345long long int __atomic_fetch_sub  (volatile long long int *, long long int, int);
    406346long long int __atomic_fetch_sub_8(volatile long long int *, long long int, int);
    407 #if defined(__SIZEOF_INT128__)
    408347__int128 __atomic_fetch_sub   (volatile __int128 *, __int128, int);
    409348__int128 __atomic_fetch_sub_16(volatile __int128 *, __int128, int);
    410 #endif
    411349
    412350char __atomic_fetch_and  (volatile char *, char, int);
     
    418356long long int __atomic_fetch_and  (volatile long long int *, long long int, int);
    419357long long int __atomic_fetch_and_8(volatile long long int *, long long int, int);
    420 #if defined(__SIZEOF_INT128__)
    421358__int128 __atomic_fetch_and   (volatile __int128 *, __int128, int);
    422359__int128 __atomic_fetch_and_16(volatile __int128 *, __int128, int);
    423 #endif
    424360
    425361char __atomic_fetch_nand  (volatile char *, char, int);
     
    431367long long int __atomic_fetch_nand  (volatile long long int *, long long int, int);
    432368long long int __atomic_fetch_nand_8(volatile long long int *, long long int, int);
    433 #if defined(__SIZEOF_INT128__)
    434369__int128 __atomic_fetch_nand   (volatile __int128 *, __int128, int);
    435370__int128 __atomic_fetch_nand_16(volatile __int128 *, __int128, int);
    436 #endif
    437371
    438372char __atomic_fetch_xor  (volatile char *, char, int);
     
    444378long long int __atomic_fetch_xor  (volatile long long int *, long long int, int);
    445379long long int __atomic_fetch_xor_8(volatile long long int *, long long int, int);
    446 #if defined(__SIZEOF_INT128__)
    447380__int128 __atomic_fetch_xor   (volatile __int128 *, __int128, int);
    448381__int128 __atomic_fetch_xor_16(volatile __int128 *, __int128, int);
    449 #endif
    450382
    451383char __atomic_fetch_or  (volatile char *, char, int);
     
    457389long long int __atomic_fetch_or  (volatile long long int *, long long int, int);
    458390long long int __atomic_fetch_or_8(volatile long long int *, long long int, int);
    459 #if defined(__SIZEOF_INT128__)
    460391__int128 __atomic_fetch_or   (volatile __int128 *, __int128, int);
    461392__int128 __atomic_fetch_or_16(volatile __int128 *, __int128, int);
    462 #endif
    463393
    464394_Bool __atomic_always_lock_free(unsigned long, const volatile void *);
  • src/tests/.gitignore

    rb21c77a r97397a26  
    11.out/
    22.err/
    3 .type
  • src/tests/Makefile.am

    rb21c77a r97397a26  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Wed Jun  6 16:42:20 2018
    14 ## Update Count     : 49
     13## Last Modified On : Mon Nov 27 21:34:33 2017
     14## Update Count     : 48
    1515###############################################################################
    1616
     
    2828DEBUG_FLAGS =
    2929
    30 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -I.
     30BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@
    3131if !BUILD_DEBUG
    3232BUILD_FLAGS += -nodebug
     
    9292        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    9393
     94literals : literals.c @CFA_BINDIR@/@CFA_NAME@
     95        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     96
    9497sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@
    9598        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/Makefile.in

    rb21c77a r97397a26  
    309309# applies to both programs
    310310DEBUG_FLAGS =
    311 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -I. \
     311BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ \
    312312        $(am__append_1) $(am__append_2) $(am__append_3)
    313313TEST_FLAGS = $(if $(test), 2> $(test), )
     
    769769        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    770770
     771literals : literals.c @CFA_BINDIR@/@CFA_NAME@
     772        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     773
    771774sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@
    772775        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/builtins/sync.c

    rb21c77a r97397a26  
    88        volatile int * vp4 = 0; int * rp4 = 0; int v4 = 0;
    99        volatile long long int * vp8 = 0; long long int * rp8 = 0; long long int v8 = 0;
    10         #if defined(__SIZEOF_INT128__)
    1110        volatile __int128 * vp16 = 0; __int128 * rp16 = 0; __int128 v16 = 0;
    12         #endif
    1311
    1412        { char ret; ret = __sync_fetch_and_add(vp1, v1); }
     
    2018        { long long int ret; ret = __sync_fetch_and_add(vp8, v8); }
    2119        { long long int ret; ret = __sync_fetch_and_add_8(vp8, v8); }
    22         #if defined(__SIZEOF_INT128__)
    2320        { __int128 ret; ret = __sync_fetch_and_add(vp16, v16); }
    2421        { __int128 ret; ret = __sync_fetch_and_add_16(vp16, v16); }
    25         #endif
    2622
    2723        { char ret; ret = __sync_fetch_and_sub(vp1, v1); }
     
    3329        { long long int ret; ret = __sync_fetch_and_sub(vp8, v8); }
    3430        { long long int ret; ret = __sync_fetch_and_sub_8(vp8, v8); }
    35         #if defined(__SIZEOF_INT128__)
    3631        { __int128 ret; ret = __sync_fetch_and_sub(vp16, v16); }
    3732        { __int128 ret; ret = __sync_fetch_and_sub_16(vp16, v16); }
    38         #endif
    3933
    4034        { char ret; ret = __sync_fetch_and_or(vp1, v1); }
     
    4640        { long long int ret; ret = __sync_fetch_and_or(vp8, v8); }
    4741        { long long int ret; ret = __sync_fetch_and_or_8(vp8, v8); }
    48         #if defined(__SIZEOF_INT128__)
    4942        { __int128 ret; ret = __sync_fetch_and_or(vp16, v16); }
    5043        { __int128 ret; ret = __sync_fetch_and_or_16(vp16, v16); }
    51         #endif
    5244
    5345        { char ret; ret = __sync_fetch_and_and(vp1, v1); }
     
    5951        { long long int ret; ret = __sync_fetch_and_and(vp8, v8); }
    6052        { long long int ret; ret = __sync_fetch_and_and_8(vp8, v8); }
    61         #if defined(__SIZEOF_INT128__)
    6253        { __int128 ret; ret = __sync_fetch_and_and(vp16, v16); }
    6354        { __int128 ret; ret = __sync_fetch_and_and_16(vp16, v16); }
    64         #endif
    6555
    6656        { char ret; ret = __sync_fetch_and_xor(vp1, v1); }
     
    7262        { long long int ret; ret = __sync_fetch_and_xor(vp8, v8); }
    7363        { long long int ret; ret = __sync_fetch_and_xor_8(vp8, v8); }
    74         #if defined(__SIZEOF_INT128__)
    7564        { __int128 ret; ret = __sync_fetch_and_xor(vp16, v16); }
    7665        { __int128 ret; ret = __sync_fetch_and_xor_16(vp16, v16); }
    77         #endif
    7866
    7967        { char ret; ret = __sync_fetch_and_nand(vp1, v1); }
     
    8573        { long long int ret; ret = __sync_fetch_and_nand(vp8, v8); }
    8674        { long long int ret; ret = __sync_fetch_and_nand_8(vp8, v8); }
    87         #if defined(__SIZEOF_INT128__)
    8875        { __int128 ret; ret = __sync_fetch_and_nand(vp16, v16); }
    8976        { __int128 ret; ret = __sync_fetch_and_nand_16(vp16, v16); }
    90         #endif
    9177
    9278        { char ret; ret = __sync_add_and_fetch(vp1, v1); }
     
    9884        { long long int ret; ret = __sync_add_and_fetch(vp8, v8); }
    9985        { long long int ret; ret = __sync_add_and_fetch_8(vp8, v8); }
    100         #if defined(__SIZEOF_INT128__)
    10186        { __int128 ret; ret = __sync_add_and_fetch(vp16, v16); }
    10287        { __int128 ret; ret = __sync_add_and_fetch_16(vp16, v16); }
    103         #endif
    10488
    10589        { char ret; ret = __sync_sub_and_fetch(vp1, v1); }
     
    11195        { long long int ret; ret = __sync_sub_and_fetch(vp8, v8); }
    11296        { long long int ret; ret = __sync_sub_and_fetch_8(vp8, v8); }
    113         #if defined(__SIZEOF_INT128__)
    11497        { __int128 ret; ret = __sync_sub_and_fetch(vp16, v16); }
    11598        { __int128 ret; ret = __sync_sub_and_fetch_16(vp16, v16); }
    116         #endif
    11799
    118100        { char ret; ret = __sync_or_and_fetch(vp1, v1); }
     
    124106        { long long int ret; ret = __sync_or_and_fetch(vp8, v8); }
    125107        { long long int ret; ret = __sync_or_and_fetch_8(vp8, v8); }
    126         #if defined(__SIZEOF_INT128__)
    127108        { __int128 ret; ret = __sync_or_and_fetch(vp16, v16); }
    128109        { __int128 ret; ret = __sync_or_and_fetch_16(vp16, v16); }
    129         #endif
    130110
    131111        { char ret; ret = __sync_and_and_fetch(vp1, v1); }
     
    137117        { long long int ret; ret = __sync_and_and_fetch(vp8, v8); }
    138118        { long long int ret; ret = __sync_and_and_fetch_8(vp8, v8); }
    139         #if defined(__SIZEOF_INT128__)
    140119        { __int128 ret; ret = __sync_and_and_fetch(vp16, v16); }
    141120        { __int128 ret; ret = __sync_and_and_fetch_16(vp16, v16); }
    142         #endif
    143121
    144122        { char ret; ret = __sync_xor_and_fetch(vp1, v1); }
     
    150128        { long long int ret; ret = __sync_xor_and_fetch(vp8, v8); }
    151129        { long long int ret; ret = __sync_xor_and_fetch_8(vp8, v8); }
    152         #if defined(__SIZEOF_INT128__)
    153130        { __int128 ret; ret = __sync_xor_and_fetch(vp16, v16); }
    154131        { __int128 ret; ret = __sync_xor_and_fetch_16(vp16, v16); }
    155         #endif
    156132
    157133        { char ret; ret = __sync_nand_and_fetch(vp1, v1); }
     
    163139        { long long int ret; ret = __sync_nand_and_fetch(vp8, v8); }
    164140        { long long int ret; ret = __sync_nand_and_fetch_8(vp8, v8); }
    165         #if defined(__SIZEOF_INT128__)
    166141        { __int128 ret; ret = __sync_nand_and_fetch(vp16, v16); }
    167142        { __int128 ret; ret = __sync_nand_and_fetch_16(vp16, v16); }
    168         #endif
    169143
    170144        { _Bool ret; ret = __sync_bool_compare_and_swap(vp1, v1, v1); }
     
    176150        { _Bool ret; ret = __sync_bool_compare_and_swap(vp8, v8, v8); }
    177151        { _Bool ret; ret = __sync_bool_compare_and_swap_8(vp8, v8, v8); }
    178         #if defined(__SIZEOF_INT128__)
    179152        { _Bool ret; ret = __sync_bool_compare_and_swap(vp16, v16, v16); }
    180153        { _Bool ret; ret = __sync_bool_compare_and_swap_16(vp16, v16,v16); }
    181         #endif
    182154
    183155        { char ret; ret = __sync_val_compare_and_swap(vp1, v1, v1); }
     
    189161        { long long int ret; ret = __sync_val_compare_and_swap(vp8, v8, v8); }
    190162        { long long int ret; ret = __sync_val_compare_and_swap_8(vp8, v8, v8); }
    191         #if defined(__SIZEOF_INT128__)
    192163        { __int128 ret; ret = __sync_val_compare_and_swap(vp16, v16, v16); }
    193164        { __int128 ret; ret = __sync_val_compare_and_swap_16(vp16, v16,v16); }
    194         #endif
    195165
    196166        { char ret; ret = __sync_lock_test_and_set(vp1, v1); }
     
    202172        { long long int ret; ret = __sync_lock_test_and_set(vp8, v8); }
    203173        { long long int ret; ret = __sync_lock_test_and_set_8(vp8, v8); }
    204         #if defined(__SIZEOF_INT128__)
    205174        { __int128 ret; ret = __sync_lock_test_and_set(vp16, v16); }
    206175        { __int128 ret; ret = __sync_lock_test_and_set_16(vp16, v16); }
    207         #endif
    208176
    209177        { __sync_lock_release(vp1); }
     
    215183        { __sync_lock_release(vp8); }
    216184        { __sync_lock_release_8(vp8); }
    217         #if defined(__SIZEOF_INT128__)
    218185        { __sync_lock_release(vp16); }
    219186        { __sync_lock_release_16(vp16); }
    220         #endif
    221187
    222188        { __sync_synchronize(); }
     
    242208        { long long int ret; ret = __atomic_exchange_8(vp8, v8, __ATOMIC_SEQ_CST); }
    243209        { long long int ret; __atomic_exchange(vp8, &v8, &ret, __ATOMIC_SEQ_CST); }
    244         #if defined(__SIZEOF_INT128__)
    245210        { __int128 ret; ret = __atomic_exchange_n(vp16, &v16, __ATOMIC_SEQ_CST); }
    246211        { __int128 ret; ret = __atomic_exchange_16(vp16, v16, __ATOMIC_SEQ_CST); }
    247212        { __int128 ret; __atomic_exchange(vp16, &v16, &ret, __ATOMIC_SEQ_CST); }
    248         #endif
    249213
    250214        { char ret; ret = __atomic_load_n(vp1, __ATOMIC_SEQ_CST); }
     
    260224        { long long int ret; ret = __atomic_load_8(vp8, __ATOMIC_SEQ_CST); }
    261225        { long long int ret; __atomic_load(vp8, &ret, __ATOMIC_SEQ_CST); }
    262         #if defined(__SIZEOF_INT128__)
    263226        { __int128 ret; ret = __atomic_load_n(vp16, __ATOMIC_SEQ_CST); }
    264227        { __int128 ret; ret = __atomic_load_16(vp16, __ATOMIC_SEQ_CST); }
    265228        { __int128 ret; __atomic_load(vp16, &ret, __ATOMIC_SEQ_CST); }
    266         #endif
    267229
    268230        { _Bool ret; ret = __atomic_compare_exchange_n(vp1, rp1, v1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
     
    278240        { _Bool ret; ret = __atomic_compare_exchange_8(vp8, rp8, v8, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    279241        { _Bool ret; ret = __atomic_compare_exchange(vp8, rp8, &v8, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    280         #if defined(__SIZEOF_INT128__)
    281242        { _Bool ret; ret = __atomic_compare_exchange_n(vp16, rp16, v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    282243        { _Bool ret; ret = __atomic_compare_exchange_16(vp16, rp16, v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    283244        { _Bool ret; ret = __atomic_compare_exchange(vp16, rp16, &v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    284         #endif
    285245
    286246        { __atomic_store_n(vp1, v1, __ATOMIC_SEQ_CST); }
     
    296256        { __atomic_store_8(vp8, v8, __ATOMIC_SEQ_CST); }
    297257        { __atomic_store(vp8, &v8, __ATOMIC_SEQ_CST); }
    298         #if defined(__SIZEOF_INT128__)
    299258        { __atomic_store_n(vp16, v16, __ATOMIC_SEQ_CST); }
    300259        { __atomic_store_16(vp16, v16, __ATOMIC_SEQ_CST); }
    301260        { __atomic_store(vp16, &v16, __ATOMIC_SEQ_CST); }
    302         #endif
    303261
    304262        { char ret; ret = __atomic_add_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    310268        { long long int ret; ret = __atomic_add_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    311269        { long long int ret; ret = __atomic_add_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    312         #if defined(__SIZEOF_INT128__)
    313270        { __int128 ret; ret = __atomic_add_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    314271        { __int128 ret; ret = __atomic_add_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    315         #endif
    316272
    317273        { char ret; ret = __atomic_sub_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    323279        { long long int ret; ret = __atomic_sub_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    324280        { long long int ret; ret = __atomic_sub_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    325         #if defined(__SIZEOF_INT128__)
    326281        { __int128 ret; ret = __atomic_sub_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    327282        { __int128 ret; ret = __atomic_sub_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    328         #endif
    329283
    330284        { char ret; ret = __atomic_and_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    336290        { long long int ret; ret = __atomic_and_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    337291        { long long int ret; ret = __atomic_and_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    338         #if defined(__SIZEOF_INT128__)
    339292        { __int128 ret; ret = __atomic_and_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    340293        { __int128 ret; ret = __atomic_and_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    341         #endif
    342294
    343295        { char ret; ret = __atomic_nand_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    349301        { long long int ret; ret = __atomic_nand_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    350302        { long long int ret; ret = __atomic_nand_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    351         #if defined(__SIZEOF_INT128__)
    352303        { __int128 ret; ret = __atomic_nand_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    353304        { __int128 ret; ret = __atomic_nand_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    354         #endif
    355305
    356306        { char ret; ret = __atomic_xor_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    362312        { long long int ret; ret = __atomic_xor_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    363313        { long long int ret; ret = __atomic_xor_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    364         #if defined(__SIZEOF_INT128__)
    365314        { __int128 ret; ret = __atomic_xor_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    366315        { __int128 ret; ret = __atomic_xor_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    367         #endif
    368316
    369317        { char ret; ret = __atomic_or_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    375323        { long long int ret; ret = __atomic_or_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    376324        { long long int ret; ret = __atomic_or_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
    377         #if defined(__SIZEOF_INT128__)
    378325        { __int128 ret; ret = __atomic_or_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    379326        { __int128 ret; ret = __atomic_or_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
    380         #endif
    381327
    382328        { char ret; ret = __atomic_fetch_add(vp1, v1, __ATOMIC_SEQ_CST); }
     
    388334        { long long int ret; ret = __atomic_fetch_add(vp8, v8, __ATOMIC_SEQ_CST); }
    389335        { long long int ret; ret = __atomic_fetch_add_8(vp8, v8, __ATOMIC_SEQ_CST); }
    390         #if defined(__SIZEOF_INT128__)
    391336        { __int128 ret; ret = __atomic_fetch_add(vp16, v16, __ATOMIC_SEQ_CST); }
    392337        { __int128 ret; ret = __atomic_fetch_add_16(vp16, v16, __ATOMIC_SEQ_CST); }
    393         #endif
    394338
    395339        { char ret; ret = __atomic_fetch_sub(vp1, v1, __ATOMIC_SEQ_CST); }
     
    401345        { long long int ret; ret = __atomic_fetch_sub(vp8, v8, __ATOMIC_SEQ_CST); }
    402346        { long long int ret; ret = __atomic_fetch_sub_8(vp8, v8, __ATOMIC_SEQ_CST); }
    403         #if defined(__SIZEOF_INT128__)
    404347        { __int128 ret; ret = __atomic_fetch_sub(vp16, v16, __ATOMIC_SEQ_CST); }
    405348        { __int128 ret; ret = __atomic_fetch_sub_16(vp16, v16, __ATOMIC_SEQ_CST); }
    406         #endif
    407349
    408350        { char ret; ret = __atomic_fetch_and(vp1, v1, __ATOMIC_SEQ_CST); }
     
    414356        { long long int ret; ret = __atomic_fetch_and(vp8, v8, __ATOMIC_SEQ_CST); }
    415357        { long long int ret; ret = __atomic_fetch_and_8(vp8, v8, __ATOMIC_SEQ_CST); }
    416         #if defined(__SIZEOF_INT128__)
    417358        { __int128 ret; ret = __atomic_fetch_and(vp16, v16, __ATOMIC_SEQ_CST); }
    418359        { __int128 ret; ret = __atomic_fetch_and_16(vp16, v16, __ATOMIC_SEQ_CST); }
    419         #endif
    420360
    421361        { char ret; ret = __atomic_fetch_nand(vp1, v1, __ATOMIC_SEQ_CST); }
     
    427367        { long long int ret; ret = __atomic_fetch_nand(vp8, v8, __ATOMIC_SEQ_CST); }
    428368        { long long int ret; ret = __atomic_fetch_nand_8(vp8, v8, __ATOMIC_SEQ_CST); }
    429         #if defined(__SIZEOF_INT128__)
    430369        { __int128 ret; ret = __atomic_fetch_nand(vp16, v16, __ATOMIC_SEQ_CST); }
    431370        { __int128 ret; ret = __atomic_fetch_nand_16(vp16, v16, __ATOMIC_SEQ_CST); }
    432         #endif
    433371
    434372        { char ret; ret = __atomic_fetch_xor(vp1, v1, __ATOMIC_SEQ_CST); }
     
    440378        { long long int ret; ret = __atomic_fetch_xor(vp8, v8, __ATOMIC_SEQ_CST); }
    441379        { long long int ret; ret = __atomic_fetch_xor_8(vp8, v8, __ATOMIC_SEQ_CST); }
    442         #if defined(__SIZEOF_INT128__)
    443380        { __int128 ret; ret = __atomic_fetch_xor(vp16, v16, __ATOMIC_SEQ_CST); }
    444381        { __int128 ret; ret = __atomic_fetch_xor_16(vp16, v16, __ATOMIC_SEQ_CST); }
    445         #endif
    446382
    447383        { char ret; ret = __atomic_fetch_or(vp1, v1, __ATOMIC_SEQ_CST); }
     
    453389        { long long int ret; ret = __atomic_fetch_or(vp8, v8, __ATOMIC_SEQ_CST); }
    454390        { long long int ret; ret = __atomic_fetch_or_8(vp8, v8, __ATOMIC_SEQ_CST); }
    455         #if defined(__SIZEOF_INT128__)
    456391        { __int128 ret; ret = __atomic_fetch_or(vp16, v16, __ATOMIC_SEQ_CST); }
    457392        { __int128 ret; ret = __atomic_fetch_or_16(vp16, v16, __ATOMIC_SEQ_CST); }
    458         #endif
    459393
    460394        { _Bool ret; ret = __atomic_always_lock_free(sizeof(int), vp4); }
  • src/tests/concurrent/coroutineYield.c

    rb21c77a r97397a26  
    44#include <thread>
    55#include <time>
    6 
    7 #define __kick_rate 150000ul
    8 #include "long_tests.h"
    96
    107#ifndef PREEMPTION_RATE
     
    1613}
    1714
    18 #ifdef TEST_LONG
     15#ifdef LONG_TEST
    1916static const unsigned long N = 600_000ul;
    2017#else
     
    2623void main(Coroutine& this) {
    2724        while(true) {
    28                 #if !defined(TEST_FOREVER)
    29                         sout | "Coroutine 1" | endl;
    30                 #endif
     25                sout | "Coroutine 1" | endl;
    3126                yield();
    32                 #if !defined(TEST_FOREVER)
    33                         sout | "Coroutine 2" | endl;
    34                 #endif
     27                sout | "Coroutine 2" | endl;
    3528                suspend();
    3629        }
     
    4033int main(int argc, char* argv[]) {
    4134        Coroutine c;
    42         for(int i = 0; TEST(i < N); i++) {
    43                 #if !defined(TEST_FOREVER)
    44                         sout | "Thread 1" | endl;
    45                 #endif
     35        for(int i = 0; i < N; i++) {
     36                sout | "Thread 1" | endl;
    4637                resume(c);
    47                 #if !defined(TEST_FOREVER)
    48                         sout | "Thread 2" | endl;
    49                 #endif
     38                sout | "Thread 2" | endl;
    5039                yield();
    51                 KICK_WATCHDOG;
    5240        }
    5341}
  • src/tests/concurrent/examples/datingService.c

    rb21c77a r97397a26  
    88// Created On       : Mon Oct 30 12:56:20 2017
    99// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Sun May 27 09:05:18 2018
    11 // Update Count     : 26
     10// Last Modified On : Wed Mar 14 22:48:40 2018
     11// Update Count     : 23
    1212//
    1313
     
    1818#include <unistd.h>                                                                             // getpid
    1919
    20 enum { CompCodes = 20 };                                                                // number of compatibility codes
     20enum { NoOfPairs = 20 };
    2121
    2222monitor DatingService {
    23         condition Girls[CompCodes], Boys[CompCodes];
     23        condition Girls[NoOfPairs], Boys[NoOfPairs];
    2424        unsigned int GirlPhoneNo, BoyPhoneNo;
    2525}; // DatingService
     
    4747} // DatingService boy
    4848
    49 unsigned int girlck[CompCodes];
    50 unsigned int boyck[CompCodes];
     49unsigned int girlck[NoOfPairs];
     50unsigned int boyck[NoOfPairs];
    5151
    5252thread Girl {
     
    8888int main() {
    8989        DatingService TheExchange;
    90         Girl * girls[CompCodes];
    91         Boy  * boys[CompCodes];
     90        Girl * girls[NoOfPairs];
     91        Boy  * boys[NoOfPairs];
    9292
    9393        srandom( /*getpid()*/ 103 );
    9494
    95         for ( unsigned int i = 0; i < CompCodes; i += 1 ) {
     95        for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
    9696                girls[i] = new( &TheExchange, i, i );
    97                 boys[i]  = new( &TheExchange, i, CompCodes - ( i + 1 ) );
     97                boys[i]  = new( &TheExchange, i, NoOfPairs - ( i + 1 ) );
    9898        } // for
    9999
    100         for ( unsigned int i = 0; i < CompCodes; i += 1 ) {
     100        for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
    101101                delete( boys[i] );
    102102                delete( girls[i] );
    103103        } // for
    104104
    105         for ( unsigned int i = 0; i < CompCodes; i += 1 ) {
     105        for ( unsigned int i = 0; i < NoOfPairs; i += 1 ) {
    106106                if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort();
    107107        } // for
  • src/tests/concurrent/preempt.c

    rb21c77a r97397a26  
    22#include <thread>
    33#include <time>
    4 
    5 #include "long_tests.h"
    64
    75#ifndef PREEMPTION_RATE
     
    1311}
    1412
    15 #ifdef TEST_LONG
     13#ifdef LONG_TEST
    1614static const unsigned long N = 30_000ul;
    1715#else
     
    3230
    3331void main(worker_t & this) {
    34         while(TEST(counter < N)) {
     32        while(counter < N) {
    3533                __cfaabi_check_preemption();
    3634                if( (counter % 7) == this.value ) {
     
    4240                }
    4341                __cfaabi_check_preemption();
    44                 KICK_WATCHDOG;
    4542        }
    4643}
  • src/tests/concurrent/signal/block.c

    rb21c77a r97397a26  
    1414#include <time>
    1515
    16 #include "long_tests.h"
    17 
    1816#ifndef PREEMPTION_RATE
    1917#define PREEMPTION_RATE 10`ms
     
    2422}
    2523
    26 #ifdef TEST_LONG
     24#ifdef LONG_TEST
    2725static const unsigned long N = 150_000ul;
    2826#else
     
    4240}
    4341
    44 void ^?{} ( global_data_t & mutex this ) {}
     42void ^?{} ( global_data_t & this ) {}
    4543
    4644global_data_t globalA, globalB;
     
    6866thread Waiter {};
    6967void main( Waiter & this ) {
    70         for( int i = 0; TEST(i < N); i++ ) {
     68        for( int i = 0; i < N; i++ ) {
    7169                wait_op( globalA, globalB, i );
    72                 KICK_WATCHDOG;
    7370        }
    7471}
  • src/tests/concurrent/signal/disjoint.c

    rb21c77a r97397a26  
    44#include <thread>
    55#include <time>
    6 
    7 #include "long_tests.h"
    86
    97#ifndef PREEMPTION_RATE
     
    1513}
    1614
    17 #ifdef TEST_LONG
     15#ifdef LONG_TEST
    1816static const unsigned long N = 300_000ul;
    1917#else
     
    2826monitor global_data_t;
    2927void ?{}( global_data_t & this );
    30 void ^?{} ( global_data_t & mutex this );
     28void ^?{} ( global_data_t & this );
    3129
    3230monitor global_data_t {
     
    4442}
    4543
    46 void ^?{} ( global_data_t & mutex this ) {}
     44void ^?{} ( global_data_t & this ) {}
    4745
    4846//------------------------------------------------------------------------------
     
    6967        }
    7068
    71         #if !defined(TEST_FOREVER)
    72                 d.counter++;
    73                 if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
    74         #endif
     69        d.counter++;
    7570
    76         return TEST(d.counter < N);
     71        if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
     72
     73        return d.counter < N;
    7774}
    7875
     
    8077
    8178void main( Waiter & this ) {
    82         while( wait( mut, data ) ) { KICK_WATCHDOG; yield(); }
     79        while( wait( mut, data ) ) { yield(); }
    8380}
    8481
     
    9794
    9895        //This is technically a mutual exclusion violation but the mutex monitor protects us
    99         bool running = TEST(data.counter < N) && data.counter > 0;
     96        bool running = data.counter < N && data.counter > 0;
    10097        if( data.state != SIGNAL && running ) {
    10198                sout | "ERROR Eager signal" | data.state | endl;
  • src/tests/concurrent/signal/wait.c

    rb21c77a r97397a26  
    1212#include <time>
    1313
    14 #define __kick_rate 12000ul
    15 #include "long_tests.h"
    16 
    1714#ifndef PREEMPTION_RATE
    1815#define PREEMPTION_RATE 10`ms
     
    2320}
    2421
    25 #ifdef TEST_LONG
     22#ifdef LONG_TEST
    2623static const unsigned long N = 375_000ul;
    2724#else
     
    9390// Waiter ABC
    9491void main( WaiterABC & this ) {
    95         for( int i = 0; TEST(i < N); i++ ) {
     92        for( int i = 0; i < N; i++ ) {
    9693                wait( condABC, globalA, globalB, globalC );
    97                 KICK_WATCHDOG;
    9894        }
    9995
     
    104100// Waiter AB
    105101void main( WaiterAB & this ) {
    106         for( int i = 0; TEST(i < N); i++ ) {
     102        for( int i = 0; i < N; i++ ) {
    107103                wait( condAB , globalA, globalB );
    108                 KICK_WATCHDOG;
    109104        }
    110105
     
    115110// Waiter AC
    116111void main( WaiterAC & this ) {
    117         for( int i = 0; TEST(i < N); i++ ) {
     112        for( int i = 0; i < N; i++ ) {
    118113                wait( condAC , globalA, globalC );
    119                 KICK_WATCHDOG;
    120114        }
    121115
     
    126120// Waiter BC
    127121void main( WaiterBC & this ) {
    128         for( int i = 0; TEST(i < N); i++ ) {
     122        for( int i = 0; i < N; i++ ) {
    129123                wait( condBC , globalB, globalC );
    130                 KICK_WATCHDOG;
    131124        }
    132125
  • src/tests/preempt_longrun/Makefile.am

    rb21c77a r97397a26  
    1919preempt=10ul\`ms
    2020debug=-debug
    21 type=LONG
    2221
    2322REPEAT = ${abs_top_srcdir}/tools/repeat
    24 WATCHDOG = ${abs_top_srcdir}/tools/watchdog
    2523TIME = /usr/bin/time -f "%E"
    2624
    27 # $(shell ./update-type $(type))
    28 # ./update-type $(type)
    29 
    30 UPDATED_TYPE = $(shell ./update-type $(type))
    31 
    32 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
     25BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
    3326CFLAGS = ${BUILD_FLAGS}
    3427CC = @CFA_BINDIR@/@CFA_NAME@
     
    3629TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
    3730
    38 # .INTERMEDIATE: ${TESTS}
     31.INTERMEDIATE: ${TESTS}
    3932
    4033all-local: ${TESTS:=.run}
    4134
    42 runall : ${TESTS:=.run}
    43         @ echo "All programs terminated normally"
     35clean-local:
     36        rm -f ${TESTS}
    4437
    45 watchall : ${TESTS:=.watch}
    46         @ echo "All programs terminated normally"
    47 
    48 compileall : ${TESTS}
    49         @ echo "Compiled"
    50 
    51 clean-local:
    52         rm -f ${TESTS} core* out.log .type
    53 
    54 % : %.c ${CC} ${UPDATED_TYPE}
     38% : %.c ${CC}
    5539        ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
    5640
    5741%.run : % ${REPEAT}
    5842        @ time ${REPEAT} -r out.log -i -s $(repeats) timeout ${max_time} ./${<}
    59         @ rm ${<}
    60         @ echo -e "${<}: SUCCESS\n"
    61 
    62 %.watch : % ${WATCHDOG}
    63         @ time ${WATCHDOG} ./${<}
    6443        @ rm ${<}
    6544        @ echo -e "${<}: SUCCESS\n"
     
    7049        @ echo -e "${<}: SUCCESS\n"
    7150
    72 ${REPEAT}: ${abs_top_srcdir}/tools/Makefile
     51${REPEAT}:
    7352        @+make -C ${abs_top_srcdir}/tools/
    74 
    75 ${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
    76         @+make -C ${abs_top_srcdir}/tools/
  • src/tests/preempt_longrun/Makefile.in

    rb21c77a r97397a26  
    452452preempt = 10ul\`ms
    453453debug = -debug
    454 type = LONG
    455454REPEAT = ${abs_top_srcdir}/tools/repeat
    456 WATCHDOG = ${abs_top_srcdir}/tools/watchdog
    457455TIME = /usr/bin/time -f "%E"
    458 
    459 # $(shell ./update-type $(type))
    460 # ./update-type $(type)
    461 UPDATED_TYPE = $(shell ./update-type $(type))
    462 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
     456BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
    463457TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
    464458all: all-am
     
    879873
    880874
    881 # .INTERMEDIATE: ${TESTS}
     875.INTERMEDIATE: ${TESTS}
    882876
    883877all-local: ${TESTS:=.run}
    884878
    885 runall : ${TESTS:=.run}
    886         @ echo "All programs terminated normally"
    887 
    888 watchall : ${TESTS:=.watch}
    889         @ echo "All programs terminated normally"
    890 
    891 compileall : ${TESTS}
    892         @ echo "Compiled"
    893 
    894879clean-local:
    895         rm -f ${TESTS} core* out.log .type
    896 
    897 % : %.c ${CC} ${UPDATED_TYPE}
     880        rm -f ${TESTS}
     881
     882% : %.c ${CC}
    898883        ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
    899884
     
    903888        @ echo -e "${<}: SUCCESS\n"
    904889
    905 %.watch : % ${WATCHDOG}
    906         @ time ${WATCHDOG} ./${<}
    907         @ rm ${<}
    908         @ echo -e "${<}: SUCCESS\n"
    909 
    910890%.time : % ${REPEAT}
    911891        @ ${REPEAT} -i -s -- $(repeats) $(TIME) -a -o times.log ./${<}
     
    913893        @ echo -e "${<}: SUCCESS\n"
    914894
    915 ${REPEAT}: ${abs_top_srcdir}/tools/Makefile
    916         @+make -C ${abs_top_srcdir}/tools/
    917 
    918 ${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
     895${REPEAT}:
    919896        @+make -C ${abs_top_srcdir}/tools/
    920897
  • src/tests/preempt_longrun/create.c

    rb21c77a r97397a26  
    22#include <thread>
    33#include <time>
    4 
    5 #include "long_tests.h"
    64
    75#ifndef PREEMPTION_RATE
     
    2119int main(int argc, char* argv[]) {
    2220        processor p;
    23         for(int i = 0; TEST(i < N); i++) {
     21        for(int i = 0; i < N; i++) {
    2422                worker_t w[7];
    25                 KICK_WATCHDOG;
    2623        }
    2724}
  • src/tests/preempt_longrun/enter.c

    rb21c77a r97397a26  
    33#include <thread>
    44#include <time>
    5 
    6 #define __kick_rate 75000ul
    7 #include "long_tests.h"
    85
    96#ifndef PREEMPTION_RATE
     
    1815
    1916monitor mon_t {};
    20 void foo( mon_t & mutex this ) {
    21         KICK_WATCHDOG;
     17
     18mon_t mon;
     19
     20void foo( mon_t & mutex this ) {}
     21
     22thread worker_t {};
     23
     24void main( worker_t & this ) {
     25        for( unsigned long i = 0; i < N; i++ ) {
     26                foo( mon );
     27        }
    2228}
    2329
    24 mon_t mon;
    25 thread worker_t {};
    26 void main( worker_t & this ) {
    27         for( unsigned long i = 0; TEST(i < N); i++ ) {
    28                 foo( mon );
    29         }
     30extern "C" {
     31static worker_t * workers;
    3032}
    3133
     
    3436        {
    3537                worker_t w[7];
     38                workers = w;
    3639        }
    3740}
  • src/tests/preempt_longrun/enter3.c

    rb21c77a r97397a26  
    33#include <thread>
    44#include <time>
    5 
    6 #define __kick_rate 75000ul
    7 #include "long_tests.h"
    85
    96#ifndef PREEMPTION_RATE
     
    2118mon_t mon1, mon2, mon3;
    2219
    23 void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {
    24         KICK_WATCHDOG;
    25 }
     20void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {}
    2621
    2722thread worker_t {};
    2823
    2924void main( worker_t & this ) {
    30         for( unsigned long i = 0; TEST(i < N); i++ ) {
     25        for( unsigned long i = 0; i < N; i++ ) {
    3126                foo( mon1, mon2, mon3 );
    3227        }
  • src/tests/preempt_longrun/processor.c

    rb21c77a r97397a26  
    22#include <thread>
    33#include <time>
    4 
    5 #include <unistd.h>
    6 
    7 #include "long_tests.h"
    84
    95#ifndef PREEMPTION_RATE
     
    1511}
    1612
    17 static const unsigned long N = 50_000ul;
     13static const unsigned long N = 5_000ul;
    1814
    1915int main(int argc, char* argv[]) {
     
    2218                p[pi] = new();
    2319        }
    24         for ( int i = 0; TEST(i < N); i++) {
     20        for ( int i = 0; i < N; i++) {
    2521                int pi = i % 15;
    2622                delete( p[pi] );
    2723                p[pi] = new();
    28                 KICK_WATCHDOG;
    29         }
    30         for ( int pi = 0; pi < 15; pi++ ) {
    31                 delete( p[pi] );
    3224        }
    3325}
  • src/tests/preempt_longrun/stack.c

    rb21c77a r97397a26  
    33#include <thread>
    44#include <time>
    5 
    6 #define __kick_rate 5000000ul
    7 #include "long_tests.h"
    85
    96#ifndef PREEMPTION_RATE
     
    1815
    1916void main(worker_t & this) {
    20         while(TEST(0)) {
    21                 volatile long long p = 5_021_609ul;
    22                 volatile long long a = 326_417ul;
    23                 volatile long long n = 1l;
    24                 for (volatile long long i = 0; i < p; i++) {
    25                         n *= a;
    26                         n %= p;
    27                         KICK_WATCHDOG;
    28                 }
     17        volatile long long p = 5_021_609ul;
     18        volatile long long a = 326_417ul;
     19        volatile long long n = 1l;
     20        for (volatile long long i = 0; i < p; i++) {
     21                n *= a;
     22                n %= p;
     23        }
    2924
    30                 if( !TEST(n == a) ) {
    31                         abort();
    32                 }
     25        if( n != a ) {
     26                abort();
    3327        }
    3428}
  • src/tests/preempt_longrun/yield.c

    rb21c77a r97397a26  
    22#include <thread>
    33#include <time>
    4 
    5 #define __kick_rate 550000ul
    6 #include "long_tests.h"
    74
    85#ifndef PREEMPTION_RATE
     
    1411}
    1512
    16 #ifdef TEST_LONG
     13#ifdef LONG_TEST
    1714static const unsigned long N = 9_750_000ul;
    1815#else
     
    2320
    2421void main(worker_t & this) {
    25         for(int i = 0; TEST(i < N); i++) {
     22        for(int i = 0; i < N; i++) {
    2623                yield();
    27                 KICK_WATCHDOG;
    2824        }
    2925}
  • src/tests/pybin/tools.py

    rb21c77a r97397a26  
    8383        return sh(cmd)
    8484
    85 def which(program):
    86     import os
    87     def is_exe(fpath):
    88         return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
    89 
    90     fpath, fname = os.path.split(program)
    91     if fpath:
    92         if is_exe(program):
    93             return program
    94     else:
    95         for path in os.environ["PATH"].split(os.pathsep):
    96             exe_file = os.path.join(path, program)
    97             if is_exe(exe_file):
    98                 return exe_file
    99 
    100     return None
    10185################################################################################
    10286#               file handling
     
    235219        return False
    236220
    237 def fancy_print(text):
    238         column = which('column')
    239         if column:
    240                 cmd = "%s 2> /dev/null" % column
    241                 print(cmd)
    242                 proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
    243                 proc.communicate(input=text)
    244         else:
    245                 print(text)
    246221
    247222settings.set_machine_default( getMachineType )
  • src/tests/raii/.expect/ctor-autogen-ERR1.txt

    rb21c77a r97397a26  
    1 raii/ctor-autogen.c:102:1 error: Unique best alternative includes deleted identifier in Cast of:
    2   Application of
    3     Deleted Expression
    4       Variable Expression: ?{}: static inline function
    5       ... with parameters
    6         _dst: reference to instance of struct Managed with body 1
    7         x: signed int
    8       ... returning nothing
     1raii/ctor-autogen.c:102:1 error: No reasonable alternatives for expression Applying untyped:
     2  Name: ?{}
     3...to:
     4  Cast of:
     5    Variable Expression: x: instance of struct Managed with body 1
     6  ... to:
     7    reference to instance of struct Managed with body 1
     8  constant expression (123 123: signed int)
    99
    10       ... deleted by: ?{}: function
    11       ... with parameters
    12         m: reference to instance of struct Managed with body 1
    13       ... returning nothing
    14       ... with body
    15         CompoundStmt
    16           Expression Statement:
    17             Application of
    18               Variable Expression: ?=?: function
    19               ... with parameters
    20                 intrinsic reference to signed int
    21                 intrinsic signed int
    22               ... returning
    23                 _retval__operator_assign: signed int
    24                 ... with attributes:
    25                   Attribute with name: unused
    26 
    27 
    28             ... to arguments
    29               Cast of:
    30                 Member Expression, with field:
    31                   x: signed int
    32                 ... from aggregate:
    33                   Cast of:
    34                     Variable Expression: m: reference to instance of struct Managed with body 1
    35                   ... to:
    36                     instance of struct Managed with body 1
    37               ... to:
    38                 reference to signed int
    39               Cast of:
    40                 constant expression (0 0: zero_t)
    41               ... to:
    42                 signed int
    43 
    44             ... with environment:
    45               Types:
    46               Non-types:
    47 
    48 
    49   ... to arguments
    50     Cast of:
    51       Variable Expression: x: instance of struct Managed with body 1
    52     ... to:
    53       reference to instance of struct Managed with body 1
    54     constant expression (123 123: signed int)
    55 
    56 ... to: nothing
  • src/tests/sum.c

    rb21c77a r97397a26  
    1111// Created On       : Wed May 27 17:56:53 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Sun Jun  3 19:23:41 2018
    14 // Update Count     : 278
     13// Last Modified On : Sat Feb 17 11:49:17 2018
     14// Update Count     : 273
    1515//
    1616
     
    1818#include <stdlib>
    1919
    20 void ?{}( int & c, zero_t ) { c = 0; }                                  // not in prelude
     20void ?{}( int & c, zero_t ) { c = 0; }
    2121
    2222trait sumable( otype T ) {
    23         void ?{}( T &, zero_t );                                                        // 0 literal constructor
     23        void ?{}( T &, zero_t );                                                        // constructor from 0 literal
    2424        T ?+?( T, T );                                                                          // assortment of additions
    2525        T ?+=?( T &, T );
     
    2929
    3030forall( otype T | sumable( T ) )                                                // use trait
    31 T sum( size_t size, T a[] ) {
    32         T total = 0;                                                                            // initialize by 0 constructor
    33         for ( size_t i = 0; i < size; i += 1 )
     31T sum( unsigned int size, T a[] ) {
     32        T total = 0;                                                                            // instantiate T from 0 by calling constructor
     33        for ( unsigned int i = 0; i < size; i += 1 )
    3434                total += a[i];                                                                  // select appropriate +
    3535        return total;
     
    111111        for ( int i = 0; i < size; i += 1, v += 1 ) {
    112112                s += (int)v;
    113                 gs.x[i] = (int)v;                                                               // set field array in generic type
     113                gs.x[i] = (int)v;                                                               // set filed array in generic type
    114114        } // for
    115115        sout | "sum from" | low | "to" | High | "is"
    116                  | sum( size, gs.x ) | ", check" | (int)s | endl; // add field array in generic type
     116                 | sum( size, gs.x ) | ", check" | (int)s | endl; // add filed array in generic type
    117117} // main
    118118
  • src/tests/test.py

    rb21c77a r97397a26  
    277277        elif options.list :
    278278                print("Listing for %s:%s"% (settings.arch.string, settings.debug.string))
    279                 fancy_print("\n".join(map(lambda t: "%s" % (t.toString()), tests)))
     279                print("\n".join(map(lambda t: "%s" % (t.toString()), tests)))
    280280
    281281        else :
  • tools/Makefile.am

    rb21c77a r97397a26  
    1818CFLAGS = -Wall -Wextra -O2 -g
    1919
    20 noinst_PROGRAMS = busy catchsig repeat watchdog
     20noinst_PROGRAMS = busy catchsig repeat
    2121
    2222busy_SOURCES     = busy.c
     
    2424catchsig_SOURCES = catchsig.c
    2525repeat_SOURCES   = repeat.c
    26 watchdog_SOURCES = watchdog.c
  • tools/Makefile.in

    rb21c77a r97397a26  
    9292build_triplet = @build@
    9393host_triplet = @host@
    94 noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT) \
    95         watchdog$(EXEEXT)
     94noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT)
    9695subdir = tools
    9796ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
     
    116115repeat_OBJECTS = $(am_repeat_OBJECTS)
    117116repeat_LDADD = $(LDADD)
    118 am_watchdog_OBJECTS = watchdog.$(OBJEXT)
    119 watchdog_OBJECTS = $(am_watchdog_OBJECTS)
    120 watchdog_LDADD = $(LDADD)
    121117AM_V_P = $(am__v_P_@AM_V@)
    122118am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    147143am__v_CCLD_0 = @echo "  CCLD    " $@;
    148144am__v_CCLD_1 =
    149 SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
    150         $(watchdog_SOURCES)
    151 DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
    152         $(watchdog_SOURCES)
     145SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
     146DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
    153147am__can_run_installinfo = \
    154148  case $$AM_UPDATE_INFO_DIR in \
     
    301295catchsig_SOURCES = catchsig.c
    302296repeat_SOURCES = repeat.c
    303 watchdog_SOURCES = watchdog.c
    304297all: all-am
    305298
     
    351344        $(AM_V_CCLD)$(LINK) $(repeat_OBJECTS) $(repeat_LDADD) $(LIBS)
    352345
    353 watchdog$(EXEEXT): $(watchdog_OBJECTS) $(watchdog_DEPENDENCIES) $(EXTRA_watchdog_DEPENDENCIES)
    354         @rm -f watchdog$(EXEEXT)
    355         $(AM_V_CCLD)$(LINK) $(watchdog_OBJECTS) $(watchdog_LDADD) $(LIBS)
    356 
    357346mostlyclean-compile:
    358347        -rm -f *.$(OBJEXT)
     
    364353@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catchsig.Po@am__quote@
    365354@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@
    366 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
    367355
    368356.c.o:
  • tools/prettyprinter/lex.ll

    rb21c77a r97397a26  
    1010 * Created On       : Sat Dec 15 11:45:59 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu May 31 08:49:58 2018
    13  * Update Count     : 274
     12 * Last Modified On : Sun Apr 15 21:28:33 2018
     13 * Update Count     : 271
    1414 */
    1515
     
    7777}
    7878
    79 <INITIAL,C_CODE>"//"[^\n]* {                                                    // C++ style comments
     79<INITIAL,C_CODE>"//"[^\n]*"\n" {                                                // C++ style comments
    8080#if defined(DEBUG_ALL) | defined(DEBUG_COMMENT)
    8181        cerr << "\"//\"[^\\n]*\"\n\" : " << yytext << endl;
Note: See TracChangeset for help on using the changeset viewer.