Changeset 28f3a19


Ignore:
Timestamp:
Jun 27, 2018, 3:28:41 PM (7 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
new-env, with_gc
Children:
b21c77a
Parents:
0182bfa (diff), 63238a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into with_gc

Files:
19 added
4 deleted
121 edited
3 moved

Legend:

Unmodified
Added
Removed
  • TabularUnified Jenkins/TestRegen

    r0182bfa r28f3a19  
    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 http://plg2:8082/dashboard.
     103generated https://cforall.uwaterloo.ca:8082/dashboard.html.
    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 http://plg2:8082/dashboard.
     120generated https://cforall.uwaterloo.ca:8082/dashboard.html.
    121121
    122122Test generation encoutered an error please see attached logs
  • TabularUnified Jenkinsfile

    r0182bfa r28f3a19  
    174174
    175175def notify_server(int wait) {
    176         sh """curl --data "wait=${wait}" -X POST http://plg2:8082/jenkins/notify > /dev/null || true"""
     176        sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca: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 http://plg2:8082/jenkins/publish > /dev/null || true'
     331                sh 'curl -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
    332332        }
    333333}
  • TabularUnified README

    r0182bfa r28f3a19  
    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         http://plg.uwaterloo.ca/~cforall
     117        https://cforall.uwaterloo.ca
  • TabularUnified doc/papers/OOPSLA17/Makefile

    r0182bfa r28f3a19  
    3333
    3434DOCUMENT = generic_types.pdf
     35BASE = ${basename ${DOCUMENT}}
    3536
    3637# Directives #
     
    4142
    4243clean :
    43         @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
     44        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    4445
    4546# File Dependencies #
    4647
    47 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     48${DOCUMENT} : ${BASE}.ps
    4849        ps2pdf $<
    4950
    50 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     51${BASE}.ps : ${BASE}.dvi
    5152        dvips ${Build}/$< -o $@
    5253
    53 ${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ../../bibliography/pl.bib
     54${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     55                ../../bibliography/pl.bib | ${Build}
    5456        # Must have *.aux file containing citations for bibtex
    5557        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6365## Define the default recipes.
    6466
    65 ${Build}:
     67${Build} :
    6668        mkdir -p ${Build}
    6769
     
    6971        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    7072
    71 %.tex : %.fig
     73%.tex : %.fig | ${Build}
    7274        fig2dev -L eepic $< > ${Build}/$@
    7375
    74 %.ps : %.fig
     76%.ps : %.fig | ${Build}
    7577        fig2dev -L ps $< > ${Build}/$@
    7678
    77 %.pstex : %.fig
     79%.pstex : %.fig | ${Build}
    7880        fig2dev -L pstex $< > ${Build}/$@
    7981        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • TabularUnified doc/papers/concurrency/Makefile

    r0182bfa r28f3a19  
    2020
    2121FIGURES = ${addsuffix .tex, \
    22 monitor \
    23 ext_monitor \
    2422int_monitor \
    2523dependency \
     
    2725
    2826PICTURES = ${addsuffix .pstex, \
     27monitor \
     28ext_monitor \
    2929system \
    3030monitor_structs \
     
    5959        dvips ${Build}/$< -o $@
    6060
    61 ${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 annex/local.bib ../../bibliography/pl.bib
     61${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                annex/local.bib ../../bibliography/pl.bib | ${Build}
    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
  • TabularUnified doc/papers/concurrency/Paper.tex

    r0182bfa r28f3a19  
    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}}}
    6158\newcommand{\uC}{$\mu$\CC}
    62 \newcommand{\cit}{\textsuperscript{[Citation Needed]}\xspace}
    63 \newcommand{\TODO}{{\Textbf{TODO}}}
     59\newcommand{\TODO}[1]{{\Textbf{#1}}}
    6460
    6561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    258254\section{Introduction}
    259255
    260 This paper provides a minimal concurrency \newterm{Abstract Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
     256This paper provides a minimal concurrency \newterm{Application Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
    261257While the simplest concurrency system is a thread and a lock, this low-level approach is hard to master.
    262258An easier approach for programmers is to support higher-level constructs as the basis of concurrency.
     
    275271Hence, there are two problems to be solved: concurrency and parallelism.
    276272While these two concepts are often combined, they are distinct, requiring different tools~\cite[\S~2]{Buhr05a}.
    277 Concurrency tools handle synchronization and mutual exclusion, while parallelism tools handle performance, cost and resource utilization.
     273Concurrency tools handle mutual exclusion and synchronization, while parallelism tools handle performance, cost, and resource utilization.
    278274
    279275The proposed concurrency API is implemented in a dialect of C, called \CFA.
     
    286282Extended versions and explanation of the following code examples are available at the \CFA website~\cite{Cforall} or in Moss~\etal~\cite{Moss18}.
    287283
    288 \CFA is an extension of ISO-C, and hence, supports all C paradigms.
     284\CFA is a non-object-oriented extension of ISO-C, and hence, supports all C paradigms.
    289285%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.
    290 Like C, the basics of \CFA revolve around structures and functions.
     286Like C, the building blocks of \CFA are structures and routines.
    291287Virtually all of the code generated by the \CFA translator respects C memory layouts and calling conventions.
    292288While \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}.
     
    300296int x = 1, y = 2, z = 3;
    301297int * p1 = &x, ** p2 = &p1,  *** p3 = &p2,      $\C{// pointers to x}$
    302         `&` r1 = x,  `&&` r2 = r1,  `&&&` r3 = r2;      $\C{// references to x}$
     298    `&` r1 = x,   `&&` r2 = r1,   `&&&` r3 = r2;        $\C{// references to x}$
    303299int * p4 = &z, `&` r4 = z;
    304300
     
    349345        'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
    350346\end{cfa}
    351 and may appear as the body of a function or nested within a function body.
     347and may appear as the body of a routine or nested within a routine body.
    352348Each expression in the expression-list provides a type and object.
    353349The type must be an aggregate type.
     
    360356
    361357\CFA maximizes the ability to reuse names via overloading to aggressively address the naming problem.
    362 Both variables and functions may be overloaded, where selection is based on types, and number of returns (as in Ada~\cite{Ada}) and arguments.
     358Both variables and routines may be overloaded, where selection is based on types, and number of returns (as in Ada~\cite{Ada}) and arguments.
    363359\begin{cquote}
    364360\vspace*{-\baselineskip}%???
     
    415411\end{cquote}
    416412Overloading is important for \CFA concurrency since the runtime system relies on creating different types to represent concurrency objects.
    417 Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions to prevent name clashes.
    418 As seen in Section~\ref{basics}, function @main@ is heavily overloaded.
    419 
    420 Variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
     413Therefore, overloading eliminates long prefixes and other naming conventions to prevent name clashes.
     414As seen in Section~\ref{basics}, routine @main@ is heavily overloaded.
     415For example, variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
    421416\begin{cfa}
    422417struct S { int `i`; int j; double m; } s;
     
    432427}
    433428\end{cfa}
    434 For parallel semantics, both @s.i@ and @t.i@ are visible the same type, so only @i@ is ambiguous without qualification.
     429For parallel semantics, both @s.i@ and @t.i@ are visible with the same type, so only @i@ is ambiguous without qualification.
    435430
    436431
     
    438433
    439434Overloading also extends to operators.
    440 Operator-overloading syntax names a routine with the operator symbol and question marks for the operands:
     435Operator-overloading syntax creates a routine name with an operator symbol and question marks for the operands:
    441436\begin{cquote}
    442437\lstDeleteShortInline@%
     
    472467\end{cquote}
    473468While 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 
    479 The 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.
    480 For example, the following sum function works for any type that supports construction from 0 and addition:
    481 \begin{cfa}
    482 forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
    483 T 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 }
    489 S sa[5];
    490 int 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}
    495 trait `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 };
    502 forall( otype T `| sumable( T )` )                      $\C{// use trait}$
    503 T sum( T a[$\,$], size_t size );
    504 \end{cfa}
    505 
    506 Assertions 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 
    510 Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
    511 \begin{cfa}
    512 forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
    513 int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
    514 double * dp = alloc();
    515 struct S {...} * sp = alloc();
    516 \end{cfa}
    517 where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    518469
    519470
     
    544495\CFA also provides @new@ and @delete@, which behave like @malloc@ and @free@, in addition to constructing and destructing objects:
    545496\begin{cfa}
    546 {       struct S s = {10};                                              $\C{// allocation, call constructor}$
    547         ...
     497{
     498        ... struct S s = {10}; ...                              $\C{// allocation, call constructor}$
    548499}                                                                                       $\C{// deallocation, call destructor}$
    549500struct S * s = new();                                           $\C{// allocation, call constructor}$
     
    551502delete( s );                                                            $\C{// deallocation, call destructor}$
    552503\end{cfa}
    553 \CFA concurrency uses object lifetime as a means of synchronization and/or mutual exclusion.
     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
     510The 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.
     511For example, the following sum routine works for any type that supports construction from 0 and addition:
     512\begin{cfa}
     513forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
     514T 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}
     520S sa[5];
     521int i = sum( sa, 5 );                                           $\C{// use S's 0 construction and +}$
     522\end{cfa}
     523The 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}
     527trait `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};
     534forall( otype T `| sumable( T )` )                      $\C{// use trait}$
     535T sum( T a[$\,$], size_t size );
     536\end{cfa}
     537
     538Assertions 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
     542Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
     543\begin{cfa}
     544forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
     545int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
     546double * dp = alloc();
     547struct S {...} * sp = alloc();
     548\end{cfa}
     549where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    554550
    555551
     
    584580\subsection{\protect\CFA's Thread Building Blocks}
    585581
    586 An important missing feature in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
     582An 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.
    587583As such, library support for threading is far from widespread.
    588 At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
    589 On 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.
     584At the time of writing the paper, neither \protect\lstinline@gcc@ nor \protect\lstinline@clang@ support \protect\lstinline@threads.h@ in their standard libraries.}.
     585In 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.
    590586As 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.
    591587Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
     
    625621\newbox\myboxA
    626622\begin{lrbox}{\myboxA}
    627 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     623\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    628624`int f1, f2, state = 1;`   // single global variables
    629625int fib() {
     
    642638        }
    643639}
    644 \end{lstlisting}
     640\end{cfa}
    645641\end{lrbox}
    646642
    647643\newbox\myboxB
    648644\begin{lrbox}{\myboxB}
    649 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     645\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    650646#define FIB_INIT `{ 0, 1 }`
    651647typedef struct { int f2, f1; } Fib;
     
    664660        }
    665661}
    666 \end{lstlisting}
     662\end{cfa}
    667663\end{lrbox}
    668664
     
    677673\newbox\myboxA
    678674\begin{lrbox}{\myboxA}
    679 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     675\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    680676`coroutine` Fib { int fn; };
    681677void main( Fib & fib ) with( fib ) {
     
    697693        }
    698694}
    699 \end{lstlisting}
     695\end{cfa}
    700696\end{lrbox}
    701697\newbox\myboxB
    702698\begin{lrbox}{\myboxB}
    703 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     699\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    704700`coroutine` Fib { int ret; };
    705701void main( Fib & f ) with( fib ) {
     
    721717
    722718
    723 \end{lstlisting}
     719\end{cfa}
    724720\end{lrbox}
    725721\subfloat[3 States, internal variables]{\label{f:Coroutine3States}\usebox\myboxA}
     
    731727
    732728Using a coroutine, it is possible to express the Fibonacci formula directly without any of the C problems.
    733 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type:
    734 \begin{cfa}
    735 `coroutine` Fib { int fn; };
    736 \end{cfa}
    737 which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface functions, @next@.
     729Figure~\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@.
    738730Like 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.
    739 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.
    740 The interface function, @next@, takes a Fibonacci instance and context switches to it using @resume@;
     731The 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@.
     732The interface routine @next@, takes a Fibonacci instance and context switches to it using @resume@;
    741733on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
    742734The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack;
     
    769761\newbox\myboxA
    770762\begin{lrbox}{\myboxA}
    771 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     763\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    772764`coroutine` Format {
    773765        char ch;   // used for communication
     
    801793        }
    802794}
    803 \end{lstlisting}
     795\end{cfa}
    804796\end{lrbox}
    805797
    806798\newbox\myboxB
    807799\begin{lrbox}{\myboxB}
    808 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     800\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    809801struct Format {
    810802        char ch;
     
    838830        format( &fmt );
    839831}
    840 \end{lstlisting}
     832\end{cfa}
    841833\end{lrbox}
    842834\subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
     
    847839\end{figure}
    848840
    849 The 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.
    850 However, 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.
     841The 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.
     842However,@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.
    852844(The trivial cycle is a coroutine resuming itself.)
    853845This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch.
     
    931923Figure~\ref{f:ProdCons} shows a producer/consumer symmetric-coroutine performing bi-directional communication.
    932924Since 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@.
    933 The @start@ function communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
     925The @start@ routine communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
    934926Then the @resume@ to @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it.
    935927@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.
     
    937929The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    938930For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine.
    939 The 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).
     931The 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).
    940932The call from the consumer to the @payment@ introduces the cycle between producer and consumer.
    941933When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed.
     
    967959\end{cfa}
    968960and the programming language (and possibly its tool set, \eg debugger) may need to understand @baseCoroutine@ because of the stack.
    969 Furthermore, 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.
     961Furthermore, the execution of constructs/destructors is in the wrong order for certain operations.
     962For 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.
    971963
    972964An alternatively is composition:
     
    980972However, there is nothing preventing wrong placement or multiple declarations.
    981973
    982 For coroutines as for threads, many implementations are based on routine pointers or function objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
     974For coroutines as for threads, many implementations are based on routine pointers or routine objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
    983975For example, Boost implements coroutines in terms of four functor object-types:
    984976\begin{cfa}
     
    988980symmetric_coroutine<>::yield_type
    989981\end{cfa}
    990 Similarly, the canonical threading paradigm is often based on function pointers, \eg @pthread@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
     982Similarly, the canonical threading paradigm is often based on routine pointers, \eg @pthreads@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
    991983However, the generic thread-handle (identifier) is limited (few operations), unless it is wrapped in a custom type.
    992984\begin{cfa}
     
    1002994\end{cfa}
    1003995Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda-based coroutines adds very little.
     996
     997Note, the type @coroutine_t@ must be an abstract handle to the coroutine, because the coroutine descriptor and its stack are non-copyable.
     998Copying the coroutine descriptor results in copies being out of date with the current state of the stack.
     999Correspondingly, 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.)
    10041001
    10051002The selected approach is to use language support by introducing a new kind of aggregate (structure):
     
    10141011Furthermore, implementing coroutines without language supports also displays the power of a programming language.
    10151012While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed without using the language support.
    1016 The reserved keyword eases use for the common cases.
    1017 
    1018 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 functions:
    1019 \begin{cfa}
    1020 trait is_coroutine( dtype T ) {
    1021       void main( T & this );
    1022       coroutine_desc * get_coroutine( T & this );
     1013The reserved keyword simply eases use for the common cases.
     1014
     1015Part 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}
     1017trait is_coroutine( `dtype` T ) {
     1018        void main( T & );
     1019        coroutine_desc * get_coroutine( T & );
    10231020};
    1024 forall( dtype T | is_coroutine(T) ) void get_coroutine( T & );
    1025 forall( dtype T | is_coroutine(T) ) void suspend( T & );
    1026 forall( dtype T | is_coroutine(T) ) void resume( T & );
    1027 \end{cfa}
    1028 This definition ensures there is a statically-typed @main@ function that is the starting point (first stack frame) of a coroutine.
    1029 No 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.
    1030 As well, any object passed to @suspend@ and @resume@ is a coroutine since it must satisfy the @is_coroutine@ trait to compile.
    1031 The 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.
     1021forall( `dtype` T | is_coroutine(T) ) void suspend( T & );
     1022forall( `dtype` T | is_coroutine(T) ) void resume( T & );
     1023\end{cfa}
     1024The @dtype@ property of the trait ensures the coroutine descriptor is non-copyable, so all coroutines must be passed by reference (pointer).
     1025The 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.
     1026The @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.
     1027The 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.
     1028The 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@.
    10321029The \CFA keyword @coroutine@ implicitly implements the getter and forward declarations required for implementing the coroutine main:
    10331030\begin{cquote}
     
    10391036};
    10401037\end{cfa}
    1041 & {\Large $\Rightarrow$} &
     1038&
     1039{\Large $\Rightarrow$}
     1040&
    10421041\begin{tabular}{@{}ccc@{}}
    10431042\begin{cfa}
     
    10731072Like 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:
    10741073\begin{cquote}
    1075 \begin{tabular}{@{}c@{\hspace{2\parindentlnth}}c@{}}
     1074\begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
    10761075\begin{cfa}
    10771076thread myThread {
     
    10831082&
    10841083\begin{cfa}
    1085 trait is_thread( dtype T ) {
    1086       void main( T & this );
    1087       thread_desc * get_thread( T & this );
    1088       void ^?{}( T & `mutex` this );
     1084trait is_thread( `dtype` T ) {
     1085      void main( T & );
     1086      thread_desc * get_thread( T & );
     1087      void ^?{}( T & `mutex` );
    10891088};
    10901089\end{cfa}
     
    10921091\end{cquote}
    10931092(The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitors}.)
    1094 Like a coroutine, the statically-typed @main@ function is the starting point (first stack frame) of a user thread.
     1093Like a coroutine, the statically-typed @main@ routine is the starting point (first stack frame) of a user thread.
    10951094The difference is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates an instance of @main@;
    10961095whereas, 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{
    1097 The \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).}
    1098 No 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.
     1096The \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.}
     1097No 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.
    10991098
    11001099\begin{comment} % put in appendix with coroutine version ???
     
    11091108
    11101109In 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.
    1111 With 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}
    1113 typedef void (*voidFunc)(int);
    1114 
    1115 thread FuncRunner {
    1116         voidFunc func;
     1110With 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}
     1112typedef void (*voidRtn)(int);
     1113
     1114thread RtnRunner {
     1115        voidRtn func;
    11171116        int arg;
    11181117};
    11191118
    1120 void ?{}(FuncRunner & this, voidFunc inFunc, int arg) {
    1121         this.func = inFunc;
     1119void ?{}(RtnRunner & this, voidRtn inRtn, int arg) {
     1120        this.func = inRtn;
    11221121        this.arg  = arg;
    11231122}
    11241123
    1125 void main(FuncRunner & this) {
    1126         // thread starts here and runs the function
     1124void main(RtnRunner & this) {
     1125        // thread starts here and runs the routine
    11271126        this.func( this.arg );
    11281127}
     
    11331132
    11341133int main() {
    1135         FuncRunner f = {hello, 42};
     1134        RtnRunner f = {hello, 42};
    11361135        return 0?
    11371136}
    11381137\end{cfa}
    1139 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}.
     1138A 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}.
    11401139\end{comment}
    11411140
     
    11861185void main( Adder & adder ) with( adder ) {
    11871186    subtotal = 0;
    1188     for ( int c = 0; c < cols; c += 1 ) {
    1189                 subtotal += row[c];
    1190     }
     1187    for ( int c = 0; c < cols; c += 1 ) { subtotal += row[c]; }
    11911188}
    11921189int main() {
     
    12101207
    12111208
    1212 \section{Synchronization / Mutual Exclusion}
     1209\section{Mutual Exclusion / Synchronization}
    12131210
    12141211Uncontrolled non-deterministic execution is meaningless.
    1215 To 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.
    1216 Since 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)).
    1217 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}).
    1218 However, 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).
    1219 This distinction means a programmers needs to learn two sets of design patterns.
     1212To 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}.
     1213Since 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).
     1214In 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}.
     1215However, 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.
     1216Hence, a programmer must learn and manipulate two sets of design patterns.
    12201217While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account.
    12211218In contrast, approaches based on statefull models more closely resemble the standard call/return programming-model, resulting in a single programming paradigm.
    12221219
    1223 At 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}.
     1220At 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}.
    12241221However, for productivity it is always desirable to use the highest-level construct that provides the necessary efficiency~\cite{Hochstein05}.
    1225 A newer approach is transactional memory~\cite{Herlihy93}.
     1222A newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}.
    12261223While 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.
    12271224
    1228 One of the most natural, elegant, and efficient mechanisms for synchronization and mutual exclusion for shared-memory systems is the \emph{monitor}.
    1229 Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}.
    1230 Many 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.
    1231 In 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.
    1232 For these reasons, this project proposes monitors as the core concurrency construct, upon which even higher-level approaches can be easily constructed..
     1225One of the most natural, elegant, and efficient mechanisms for mutual exclusion and synchronization for shared-memory systems is the \emph{monitor}.
     1226First 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}.
     1227In 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.
     1228For these reasons, \CFA selected monitors as the core high-level concurrency-construct, upon which higher-level approaches can be easily constructed.
    12331229
    12341230
     
    12361232
    12371233A group of instructions manipulating a specific instance of shared data that must be performed atomically is called an (individual) \newterm{critical-section}~\cite{Dijkstra65}.
    1238 A 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.
     1234The 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.
    12391235The 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.
    1240 \newterm{Mutual exclusion} enforces the correction number of threads are using a critical section at the same time.
     1236\newterm{Mutual exclusion} enforces that the correct kind and number of threads are using a critical section.
    12411237
    12421238However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use.
    12431239Methods 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.
    1244 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.
    1245 For 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).
    1246 However, a significant challenge with (low-level) locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
    1247 Easing composability is another feature higher-level mutual-exclusion mechanisms offer.
     1240Ease 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.
     1241For 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.
     1242However, a significant challenge with locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
     1243Easing composability is another feature higher-level mutual-exclusion mechanisms can offer.
    12481244
    12491245
     
    12511247
    12521248Synchronization enforces relative ordering of execution, and synchronization tools provide numerous mechanisms to establish these timing relationships.
    1253 Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use.
    1254 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.
    1255 As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}.
    1256 Often 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
    1257 If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, the reader has \newterm{barged}.
    1258 Barging 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.
     1249Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use;
     1250higher-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.
     1251Often 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.
     1252If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, that reader has \newterm{barged}.
     1253Barging 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).
    12591254Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
    1260 This challenge is often split into two different approaches, barging avoidance and barging prevention.
    1261 Algorithms 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.
    1262 baton-pass locks~\cite{Andrews89} between threads instead of releasing the locks are said to be using barging prevention.
     1255This challenge is often split into two different approaches: barging avoidance and barging prevention.
     1256Algorithms that allow a barger, but divert it until later using current synchronization state (flags), are avoiding the barger;
     1257algorithms that preclude a barger from entering during synchronization in the critical section prevent barging completely.
     1258Techniques like baton-pass locks~\cite{Andrews89} between threads instead of unconditionally releasing locks is an example of barging prevention.
    12631259
    12641260
     
    12661262\label{s:Monitors}
    12671263
    1268 A \textbf{monitor} is a set of routines that ensure mutual-exclusion when accessing shared state.
    1269 More 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.
    1270 This strong association eases readability and maintainability, at the cost of flexibility.
    1271 Note that both monitors and mutex locks, require an abstract handle to identify them.
    1272 This concept is generally associated with object-oriented languages like Java~\cite{Java} or \uC~\cite{uC++book} but does not strictly require OO semantics.
    1273 The 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}
    1275 typedef /*some monitor type*/ monitor;
    1276 int f(monitor & m);
    1277 
    1278 int 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 % ======================================================================
    1289 The above monitor example displays some of the intrinsic characteristics.
    1290 First, it is necessary to use pass-by-reference over pass-by-value for monitor routines.
    1291 This semantics is important, because at their core, monitors are implicit mutual-exclusion objects (locks), and these objects cannot be copied.
    1292 Therefore, monitors are non-copy-able objects (@dtype@).
    1293 
    1294 Another aspect to consider is when a monitor acquires its mutual exclusion.
    1295 For example, a monitor may need to be passed through multiple helper routines that do not acquire the monitor mutual-exclusion on entry.
    1296 Passthrough 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}
    1299 monitor counter_t { /*...see section $\ref{data}$...*/ };
    1300 
    1301 void ?{}(counter_t & nomutex this); // constructor
    1302 size_t ++?(counter_t & mutex this); // increment
    1303 
    1304 // need for mutex is platform dependent
    1305 void ?{}(size_t * this, counter_t & mutex cnt); // conversion
    1306 \end{cfa}
    1307 This 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
    1312 counter_t cnt1, cnt2;
    1313 
    1314 // multiple threads access counter
    1315 thread 1 : cnt1++; cnt2++;
    1316 thread 2 : cnt1++; cnt2++;
    1317 thread 3 : cnt1++; cnt2++;
    1318         ...
    1319 thread N : cnt1++; cnt2++;
    1320 \end{cfa}
    1321 \end{tabular}
    1322 \end{center}
    1323 Notice 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 
    1325 Here, the constructor (@?{}@) uses the @nomutex@ keyword to signify that it does not acquire the monitor mutual-exclusion when constructing.
    1326 This semantics is because an object not yet constructed should never be shared and therefore does not require mutual exclusion.
    1327 Furthermore, it allows the implementation greater freedom when it initializes the monitor locking.
    1328 The prefix increment operator uses @mutex@ to protect the incrementing process from race conditions.
    1329 Finally, there is a conversion operator from @counter_t@ to @size_t@.
    1330 This conversion may or may not require the @mutex@ keyword depending on whether or not reading a @size_t@ is an atomic operation.
    1331 
    1332 For maximum usability, monitors use \textbf{multi-acq} semantics, which means a single thread can acquire the same monitor multiple times without deadlock.
    1333 For 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}]
    1336 monitor printer { ... };
    1337 struct tree {
    1338         tree * left, right;
    1339         char * value;
     1264A \textbf{monitor} is a set of routines that ensure mutual exclusion when accessing shared state.
     1265More 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).
     1266The strong association with the call/return paradigm eases programmability, readability and maintainability, at a slight cost in flexibility and efficiency.
     1267
     1268Note, 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.
     1269Copying 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.
     1270Copying 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.
     1271As 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}
     1273trait is_monitor( `dtype` T ) {
     1274        monitor_desc * get_monitor( T & );
     1275        void ^?{}( T & mutex );
    13401276};
    1341 void print(printer & mutex p, char * v);
    1342 
    1343 void 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 
    1351 Having both @mutex@ and @nomutex@ keywords can be redundant, depending on the meaning of a routine having neither of these keywords.
    1352 For 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.
    1353 On the other hand, @nomutex@ is the ``normal'' parameter behaviour, it effectively states explicitly that ``this routine is not special''.
    1354 Another alternative is making exactly one of these keywords mandatory, which provides the same semantics but without the ambiguity of supporting routines with neither keyword.
    1355 Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing.
    1356 While there are several benefits to mandatory keywords, they do bring a few challenges.
    1357 Mandatory keywords in \CFA would imply that the compiler must know without doubt whether or not a parameter is a monitor or not.
     1277\end{cfa}
     1278
     1279
     1280\subsection{Mutex Acquisition}
     1281\label{s:MutexAcquisition}
     1282
     1283While 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.)
     1285For 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]
     1287monitor Aint { int cnt; };                                      $\C{// atomic integer counter}$
     1288void ?{}( Aint & `nomutex` this ) with( this ) { cnt = 0; } $\C{// constructor}$
     1289int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions}$
     1290void ?{}( int & this, Aint & `mutex`$\(_{opt}\)$ v ) { this = v.cnt; }
     1291int ?=?( int & lhs, Aint & `mutex`$\(_{opt}\)$ rhs ) with( rhs ) { lhs = cnt; }
     1292int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
     1293\end{cfa}
     1294The @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.)
     1296The conversion operators for initializing and assigning with a normal integer only need @mutex@, if reading/writing the implementation type is not atomic.
     1297Finally, 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
     1299The 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}
     1301Aint x, y, z;
     1302++x; ++y; ++z;                                                          $\C{// safe increment by multiple threads}$
     1303x = 2; y = 2; z = 2;                                            $\C{// conversions}$
     1304int i = x, j = y, k = z;
     1305i = x; j = y; k = z;
     1306\end{cfa}
     1307
     1308For maximum usability, monitors have \newterm{multi-acquire} semantics allowing a thread to acquire it multiple times without deadlock.
     1309For example, atomically printing the contents of a binary tree:
     1310\begin{cfa}
     1311monitor Tree {
     1312        Tree * left, right;
     1313        // value
     1314};
     1315void 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
     1322Mandatory monitor qualifiers have the benefit of being self-documented, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameter is redundant.
     1323Instead, one of qualifier semantics can be the default, and the other required.
     1324For example, assume the safe @mutex@ option for a monitor parameter because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
     1325On the other hand, assuming \lstinline[morekeywords=nomutex]@nomutex@ is the \emph{normal} parameter behaviour, stating explicitly ``this parameter is not special''.
     1326Providing a default qualifier implies knowing whether a parameter is a monitor.
    13581327Since \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.
    1359 For this reason, \CFA only has the @mutex@ keyword and uses no keyword to mean @nomutex@.
    1360 
    1361 The next semantic decision is to establish when @mutex@ may be used as a type qualifier.
    1362 Consider the following declarations:
    1363 \begin{cfa}
    1364 int f1(monitor & mutex m);
    1365 int f2(const monitor & mutex m);
    1366 int f3(monitor ** mutex m);
    1367 int f4(monitor * mutex m []);
    1368 int f5(graph(monitor *) & mutex m);
    1369 \end{cfa}
    1370 The problem is to identify which object(s) should be acquired.
    1371 Furthermore, each object needs to be acquired only once.
    1372 In the case of simple routines like @f1@ and @f2@ it is easy to identify an exhaustive list of objects to acquire on entry.
    1373 Adding indirections (@f3@) still allows the compiler and programmer to identify which object is acquired.
    1374 However, adding in arrays (@f4@) makes it much harder.
    1375 Array lengths are not necessarily known in C, and even then, making sure objects are only acquired once becomes none-trivial.
    1376 This problem can be extended to absurd limits like @f5@, which uses a graph of monitors.
    1377 To 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).
    1378 Also 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.
    1379 However, this ambiguity is part of the C type-system with respects to arrays.
    1380 For this reason, @mutex@ is disallowed in the context where arrays may be passed:
    1381 \begin{cfa}
    1382 int f1(monitor & mutex m);    // Okay : recommended case
    1383 int f2(monitor * mutex m);    // Not Okay : Could be an array
    1384 int f3(monitor mutex m []);  // Not Okay : Array of unknown length
    1385 int f4(monitor ** mutex m);   // Not Okay : Could be an array
    1386 int f5(monitor * mutex m []); // Not Okay : Array of unknown length
    1387 \end{cfa}
    1388 Note that not all array functions are actually distinct in the type system.
    1389 However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
    1390 
    1391 Unlike 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.
    1392 A consequence of this approach is that it extends naturally to multi-monitor calls.
    1393 \begin{cfa}
    1394 int f(MonitorA & mutex a, MonitorB & mutex b);
    1395 
    1396 MonitorA a;
    1397 MonitorB b;
    1398 f(a,b);
    1399 \end{cfa}
    1400 While OO monitors could be extended with a mutex qualifier for multiple-monitor calls, no example of this feature could be found.
    1401 The capability to acquire multiple locks before entering a critical section is called \emph{\textbf{bulk-acq}}.
    1402 In practice, writing multi-locking routines that do not lead to deadlocks is tricky.
     1328For 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
     1330The next semantic decision is establishing which parameter \emph{types} may be qualified with @mutex@.
     1331Given:
     1332\begin{cfa}
     1333monitor M { ... }
     1334int f1( M & mutex m );
     1335int f2( M * mutex m );
     1336int f3( M * mutex m[] );
     1337int f4( stack( M * ) & mutex m );
     1338\end{cfa}
     1339the issue is that some of these parameter types are composed of multiple objects.
     1340For @f1@, there is only a single parameter object.
     1341Adding indirection in @f2@ still identifies a single object.
     1342However, the matrix in @f3@ introduces multiple objects.
     1343While shown shortly, multiple acquisition is possible;
     1344however array lengths are often unknown in C.
     1345This issue is exacerbated in @f4@, where the data structure must be safely traversed to acquire all of its elements.
     1346
     1347To make the issue tractable, \CFA only acquires one monitor per parameter with at most one level of indirection.
     1348However, the C type-system has an ambiguity with respects to arrays.
     1349Is the argument for @f2@ a single object or an array of objects?
     1350If it is an array, only the first element of the array is acquired, which seems unsafe;
     1351hence, @mutex@ is disallowed for array parameters.
     1352\begin{cfa}
     1353int f1( M & mutex m );                                          $\C{// allowed: recommended case}$
     1354int f2( M * mutex m );                                          $\C{// disallowed: could be an array}$
     1355int f3( M mutex m[$\,$] );                                      $\C{// disallowed: array length unknown}$
     1356int f4( M ** mutex m );                                         $\C{// disallowed: could be an array}$
     1357int 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
     1362For 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.
     1364A positive consequence of this design decision is the ability to support multi-monitor routines.
     1365\begin{cfa}
     1366int f( M & mutex x, M & mutex y );              $\C{// multiple monitor parameter of any type}$
     1367M m1, m2;
     1368f( 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.)
     1371In practice, writing multi-locking routines that do not deadlock is tricky.
    14031372Having language support for such a feature is therefore a significant asset for \CFA.
    1404 In the case presented above, \CFA guarantees that the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
    1405 This consistent ordering means acquiring multiple monitors is safe from deadlock when using \textbf{bulk-acq}.
    1406 However, users can still force the acquiring order.
    1407 For example, notice which routines use @mutex@/@nomutex@ and how this affects acquiring order:
    1408 \begin{cfa}
    1409 void foo(A& mutex a, B& mutex b) { // acquire a & b
    1410         ...
    1411 }
    1412 
    1413 void bar(A& mutex a, B& /*nomutex*/ b) { // acquire a
    1414         ... foo(a, b); ... // acquire b
    1415 }
    1416 
    1417 void baz(A& /*nomutex*/ a, B& mutex b) { // acquire b
    1418         ... foo(a, b); ... // acquire a
    1419 }
    1420 \end{cfa}
    1421 The \textbf{multi-acq} monitor lock allows a monitor lock to be acquired by both @bar@ or @baz@ and acquired again in @foo@.
    1422 In the calls to @bar@ and @baz@ the monitors are acquired in opposite order.
    1423 
    1424 However, such use leads to lock acquiring order problems.
    1425 In the example above, the user uses implicit ordering in the case of function @foo@ but explicit ordering in the case of @bar@ and @baz@.
    1426 This subtle difference means that calling these routines concurrently may lead to deadlock and is therefore undefined behaviour.
    1427 As 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}
    1432 While 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}.
    1433 In \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.
    1434 While \CFA provides only a partial solution, most systems provide no solution and the \CFA partial solution handles many useful cases.
    1435 
    1436 For example, \textbf{multi-acq} and \textbf{bulk-acq} can be used together in interesting ways:
    1437 \begin{cfa}
    1438 monitor bank { ... };
    1439 
    1440 void deposit( bank & mutex b, int deposit );
    1441 
    1442 void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
    1443         deposit( mybank, -me2you );
    1444         deposit( yourbank, me2you );
     1373
     1374The capability to acquire multiple locks before entering a critical section is called \newterm{bulk acquire}.
     1375In the previous example, \CFA guarantees the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
     1376This consistent ordering means acquiring multiple monitors is safe from deadlock.
     1377However, users can force the acquiring order.
     1378For example, notice the use of @mutex@/\lstinline[morekeywords=nomutex]@nomutex@ and how this affects the acquiring order:
     1379\begin{cfa}
     1380void foo( M & mutex m1, M & mutex m2 );         $\C{// acquire m1 and m2}$
     1381void bar( M & mutex m1, M & /* nomutex */ m2 ) { $\C{// acquire m1}$
     1382        ... foo( m1, m2 ); ...                                  $\C{// acquire m2}$
     1383}
     1384void baz( M & /* nomutex */ m1, M & mutex m2 ) { $\C{// acquire m2}$
     1385        ... foo( m1, m2 ); ...                                  $\C{// acquire m1}$
     1386}
     1387\end{cfa}
     1388The multi-acquire semantics allows @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
     1389In the calls to @bar@ and @baz@, the monitors are acquired in opposite order.
     1390
     1391However, 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}.
     1392In \CFA, safety is guaranteed by using bulk acquire of all monitors to shared objects, whereas other monitor systems provide no aid.
     1393While \CFA provides only a partial solution, the \CFA partial solution handles many useful cases.
     1394\begin{cfa}
     1395monitor Bank { ... };
     1396void deposit( Bank & `mutex` b, int deposit );
     1397void transfer( Bank & `mutex` mybank, Bank & `mutex` yourbank, int me2you) {
     1398        deposit( mybank, `-`me2you );                   $\C{// debit}$
     1399        deposit( yourbank, me2you );                    $\C{// credit}$
    14451400}
    14461401\end{cfa}
    14471402This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
    1448 Without \textbf{multi-acq} and \textbf{bulk-acq}, the solution to this problem is much more involved and requires careful engineering.
     1403Without multi- and bulk acquire, the solution to this problem requires careful engineering.
    14491404
    14501405
    14511406\subsection{\protect\lstinline|mutex| statement} \label{mutex-stmt}
    14521407
    1453 The 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}.
    1454 Table \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.
    1455 Beyond 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|}
    1460 function call & @mutex@ statement \\
    1461 \hline
    1462 \begin{cfa}[tabsize=3]
     1408The monitor call-semantics associate all locking semantics to routines.
     1409Like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
     1410\begin{cquote}
     1411\begin{tabular}{@{}c|@{\hspace{\parindentlnth}}c@{}}
     1412routine call & @mutex@ statement \\
     1413\begin{cfa}
    14631414monitor M {};
    14641415void foo( M & mutex m1, M & mutex m2 ) {
    14651416        // critical section
    14661417}
    1467 
    14681418void bar( M & m1, M & m2 ) {
    14691419        foo( m1, m2 );
    14701420}
    1471 \end{cfa}&\begin{cfa}[tabsize=3]
    1472 monitor M {};
     1421\end{cfa}
     1422&
     1423\begin{cfa}
     1424
    14731425void bar( M & m1, M & m2 ) {
    1474         mutex(m1, m2) {
     1426        mutex( m1, m2 ) {       // remove refactoring and naming
    14751427                // critical section
    14761428        }
    14771429}
    14781430
    1479 
    14801431\end{cfa}
    14811432\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 % ======================================================================
    1492 Once the call semantics are established, the next step is to establish data semantics.
    1493 Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data.
    1494 This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection.
    1495 For example, here is a complete version of the counter shown in section \ref{call}:
    1496 \begin{cfa}
    1497 monitor counter_t {
    1498         int value;
     1433\end{cquote}
     1434
     1435
     1436\section{Scheduling}
     1437\label{s:Scheduling}
     1438
     1439While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed.
     1440For example, Figure~\ref{f:GenericBoundedBuffer} shows a bounded buffer that may be full/empty so produce/consumer threads must block.
     1441Leaving the monitor and trying again (busy waiting) is impractical for high-level programming.
     1442Monitors 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.
     1443Synchronization 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
     1446Figure~\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@.
     1447The @wait@ routine atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the routine's parameter list.
     1448The appropriate condition lock is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
     1449Signalling is unconditional, because signalling an empty condition lock does nothing.
     1450
     1451Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means:
     1452\begin{enumerate}
     1453\item
     1454The signalling thread returns immediately, and the signalled thread continues.
     1455\item
     1456The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
     1457\item
     1458The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues.
     1459\end{enumerate}
     1460The 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.
     1462Finally, while it is common to store a @condition@ as a field of the monitor, in \CFA, a @condition@ variable can be created/stored independently.
     1463Furthermore, 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]
     1470forall( 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;
     1478        }
     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]
     1499forall( 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}
     1530\end{figure}
     1531
     1532Figure~\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.
     1533External 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.
     1534If 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.
     1535Threads 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.
     1537External scheduling allows users to wait for events from other threads without concern of unrelated events occurring.
     1538The mechnaism can be done in terms of control flow, \eg Ada @accept@ or \uC @_Accept@, or in terms of data, \eg Go channels.
     1539While both mechanisms have strengths and weaknesses, this project uses a control-flow mechanism to stay consistent with other language semantics.
     1540Two 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
     1542For internal scheduling, non-blocking signalling (as in the producer/consumer example) is used when the signaller is providing the cooperation for a waiting thread;
     1543the 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.
     1544The waiter unblocks next, uses/takes the state, and exits the monitor.
     1545Blocking signalling is the reverse, where the waiter is providing the cooperation for the signalling thread;
     1546the 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.
     1547The waiter changes state and exits the monitor, and the signaller unblocks next from the urgent queue to use/take the state.
     1548
     1549Figure~\ref{f:DatingService} shows a dating service demonstrating the two forms of signalling: non-blocking and blocking.
     1550The dating service matches girl and boy threads with matching compatibility codes so they can exchange phone numbers.
     1551A thread blocks until an appropriate partner arrives.
     1552The complexity is exchanging phone number in the monitor because the monitor mutual-exclusion property prevents exchanging numbers.
     1553For 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.
     1554For 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
     1556The 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;
     1557as 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]
     1564enum { CCodes = 20 };
     1565monitor DS {
     1566        int GirlPhNo, BoyPhNo;
     1567        condition Girls[CCodes], Boys[CCodes];
     1568        condition exchange;
    14991569};
    1500 
    1501 void ?{}(counter_t & this) {
    1502         this.cnt = 0;
    1503 }
    1504 
    1505 int ?++(counter_t & mutex this) {
    1506         return ++this.value;
    1507 }
    1508 
    1509 // need for mutex is platform dependent here
    1510 void ?{}(int * this, counter_t & mutex cnt) {
    1511         *this = (int)cnt;
    1512 }
    1513 \end{cfa}
    1514 
    1515 Like threads and coroutines, monitors are defined in terms of traits with some additional language support in the form of the @monitor@ keyword.
    1516 The monitor trait is:
    1517 \begin{cfa}
    1518 trait is_monitor(dtype T) {
    1519         monitor_desc * get_monitor( T & );
    1520         void ^?{}( T & mutex );
     1570int 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}
     1582int 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
     1592monitor DS {
     1593        int GirlPhNo, BoyPhNo;
     1594        condition Girls[CCodes], Boys[CCodes];
     1595
    15211596};
    1522 \end{cfa}
    1523 Note that the destructor of a monitor must be a @mutex@ routine to prevent deallocation while a thread is accessing the monitor.
    1524 As 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 % ======================================================================
    1531 In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronization.
    1532 With monitors, this capability is generally achieved with internal or external scheduling as in~\cite{Hoare74}.
    1533 With \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).
    1534 Since internal scheduling within a single monitor is mostly a solved problem, this paper concentrates on extending internal scheduling to multiple monitors.
    1535 Indeed, 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 
    1537 First, here is a simple example of internal scheduling:
    1538 
    1539 \begin{cfa}
    1540 monitor A {
    1541         condition e;
    1542 }
    1543 
    1544 void foo(A& mutex a1, A& mutex a2) {
     1597int 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}
     1609int 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
     1622Both 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}
     1626monitor M { `condition e`; ... };
     1627void 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}
     1635void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
     1636void rtn$\(_2\)$( M & mutex m1 );
     1637void 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}
     1644For @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 )@.
     1645To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
     1646Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.
     1647Finally, a signaller,
     1648\begin{cfa}
     1649void baz( M & mutex m1, M & mutex m2 ) {
     1650        ... signal( e ); ...
     1651}
     1652\end{cfa}
     1653must 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
     1655Similarly, 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 )@.
     1656To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
     1657Waitfor statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer.
     1658To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible.
     1659
     1660Given the ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
     1661\begin{cfa}
     1662void foo( M & mutex m1, M & mutex m2 ) {
     1663        ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
     1664void bar( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
     1665        ... signal( `e` ); ...
     1666\end{cfa}
     1667The @wait@ only releases @m1@ so the signalling thread cannot acquire both @m1@ and @m2@ to  enter @bar@ to get to the @signal@.
     1668While 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
     1670Finally, an important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
     1671If 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}
     1673However, 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.
     1674It 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.
     1677For example, there are no loops in either bounded buffer solution in Figure~\ref{f:GenericBoundedBuffer}.
     1678Supporting 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
     1683Figure~\ref{f:BargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
     1684The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
     1685The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
     1686When 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.
     1687However, 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]
     1693monitor M m1, m2;
     1694condition c;
     1695mutex( m1 ) { // $\LstCommentStyle{\color{red}outer}$
    15451696        ...
    1546         // Wait for cooperation from bar()
    1547         wait(a1.e);
     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
     1711mutex( m1 ) {
    15481712        ...
    1549 }
    1550 
    1551 void bar(A& mutex a1, A& mutex a2) {
    1552         // Provide cooperation for foo()
    1553         ...
    1554         // Unblock foo
    1555         signal(a1.e);
    1556 }
    1557 \end{cfa}
    1558 There are two details to note here.
    1559 First, @signal@ is a delayed operation; it only unblocks the waiting thread when it reaches the end of the critical section.
    1560 This semantics is needed to respect mutual-exclusion, \ie the signaller and signalled thread cannot be in the monitor simultaneously.
    1561 The alternative is to return immediately after the call to @signal@, which is significantly more restrictive.
    1562 Second, 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.
    1563 Here routine @foo@ waits for the @signal@ from @bar@ before making further progress, ensuring a basic ordering.
    1564 
    1565 An 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).
    1566 This guarantee offers the benefit of not having to loop around waits to recheck that a condition is met.
    1567 The 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.
    1568 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.
    1569 
    1570 % ======================================================================
    1571 % ======================================================================
    1572 \subsection{Internal Scheduling - Multi-Monitor}
    1573 % ======================================================================
    1574 % ======================================================================
    1575 It is easy to understand the problem of multi-monitor scheduling using a series of pseudo-code examples.
    1576 Note 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.
    1577 Indeed, @wait@ statements always use the implicit condition variable as parameters and explicitly name the monitors (A and B) associated with the condition.
    1578 Note 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.
    1579 The example below shows the simple case of having two threads (one for each column) and a single monitor A.
    1580 
    1581 \begin{multicols}{2}
    1582 thread 1
    1583 \begin{cfa}
    1584 acquire A
    1585         wait A
    1586 release A
    1587 \end{cfa}
    1588 
    1589 \columnbreak
    1590 
    1591 thread 2
    1592 \begin{cfa}
    1593 acquire A
    1594         signal A
    1595 release A
    1596 \end{cfa}
    1597 \end{multicols}
    1598 One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling.
    1599 It is important to note here that both @wait@ and @signal@ must be called with the proper monitor(s) already acquired.
    1600 This semantic is a logical requirement for barging prevention.
    1601 
    1602 A direct extension of the previous example is a \textbf{bulk-acq} version:
    1603 \begin{multicols}{2}
    1604 \begin{cfa}
    1605 acquire A & B
    1606         wait A & B
    1607 release A & B
    1608 \end{cfa}
    1609 \columnbreak
    1610 \begin{cfa}
    1611 acquire A & B
    1612         signal A & B
    1613 release 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.
    1617 Synchronization happens between the two threads in exactly the same way and order.
    1618 The only difference is that mutual exclusion covers a group of monitors.
    1619 On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
    1620 
    1621 While 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.
    1622 For 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.
    1623 For example, the following cfa-code runs into the nested-monitor problem:
    1624 \begin{multicols}{2}
    1625 \begin{cfa}
    1626 acquire A
    1627         acquire B
    1628                 wait B
    1629         release B
    1630 release A
    1631 \end{cfa}
    1632 
    1633 \columnbreak
    1634 
    1635 \begin{cfa}
    1636 acquire A
    1637         acquire B
    1638                 signal B
    1639         release B
    1640 release 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@.
    1644 Attempting 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 
    1646 However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly.
    1647 For 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}
    1651 acquire A
    1652         acquire B
    1653                 wait B
    1654         release B
    1655 release A
    1656 \end{cfa}
    1657 
    1658 \columnbreak
    1659 
    1660 \begin{cfa}
    1661 
    1662 acquire B
    1663         signal B
    1664 release 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 
    1677 A larger example is presented to show complex issues for \textbf{bulk-acq} and its implementation options are analyzed.
    1678 Figure~\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}.
    1679 For 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}
    1683 Waiting thread
    1684 \begin{cfa}[numbers=left]
    1685 acquire 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
    1693 release A
    1694 \end{cfa}
    1695 \columnbreak
    1696 Signalling thread
    1697 \begin{cfa}[numbers=left, firstnumber=10,escapechar=|]
    1698 acquire 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]
    1713 monitor A a;
    1714 monitor B b;
    1715 condition c;
    1716 \end{cfa}
    1717 \end{center}
    1718 \begin{multicols}{2}
    1719 Waiting thread
    1720 \begin{cfa}
    1721 mutex(a) {
    1722         // Code Section 1
    1723         mutex(a, b) {
    1724                 // Code Section 2
    1725                 wait(c);
    1726                 // Code Section 3
    1727         }
    1728         // Code Section 4
    1729 }
    1730 \end{cfa}
    1731 \columnbreak
    1732 Signalling thread
    1733 \begin{cfa}
    1734 mutex(a) {
    1735         // Code Section 5
    1736         mutex(a, b) {
    1737                 // Code Section 6
    1738                 signal(c);
    1739                 // Code Section 7
    1740         }
    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}
    1748 Waiter
    1749 \begin{cfa}[numbers=left]
    1750 acquire A
    1751         acquire A & B
    1752                 wait A & B
    1753         release A & B
    1754 release A
    1755 \end{cfa}
    1756 
    1757 \columnbreak
    1758 
    1759 Signaller
    1760 \begin{cfa}[numbers=left, firstnumber=6,escapechar=|]
    1761 acquire A
    1762         acquire A & B
    1763                 signal A & B
    1764         release A & B
    1765         |\label{line:secret}|// Secretly keep B here
    1766 release 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}
     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
     1727mutex( 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}
    17721747\end{figure}
    17731748
    1774 The 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.
    1775 The 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.
    1776 When 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.
    1777 This 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@.
    1778 There are three options:
    1779 
    1780 \subsubsection{Delaying Signals}
    1781 The 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.
    1782 It 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.
    1783 This 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.
    1784 This solution releases the monitors once every monitor in a group can be released.
    1785 However, since some monitors are never released (\eg the monitor of a thread), this interpretation means a group might never be released.
    1786 A 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 
    1788 However, 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.
     1749One 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.
     1750However, Figure~\ref{f:OtherWaitingThread} shows this solution is complex depending on other waiters, resulting is choices when the signaller finishes the inner mutex-statement.
     1751The 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@.
     1752In 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.
     1753Furthermore, there is an execution sequence where the signaller always finds waiter W2, and hence, waiter W1 starves.
     1754
     1755While a number of approaches were examined~\cite[\S~4.3]{Delisle18}, the solution chosen for \CFA is a novel techique called \newterm{partial signalling}.
     1756Signalled threads are moved to an urgent queue and the waiter at the front defines the set of monitors necessary for it to unblock.
     1757Partial signalling transfers ownership of monitors to the front waiter.
     1758When the signaller thread exits or waits in the monitor the front waiter is unblocked if all its monitors are released.
     1759This 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}
    17891762Figure~\ref{f:dependency} shows a slightly different example where a third thread is waiting on monitor @A@, using a different condition variable.
    17901763Because the third thread is signalled when secretly holding @B@, the goal  becomes unreachable.
     
    18001773In 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.
    18011774
     1775
    18021776\subsubsection{Dependency graphs}
    1803 
    18041777
    18051778\begin{figure}
     
    18781851The 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.
    18791852Resolving dependency graphs being a complex and expensive endeavour, this solution is not the preferred one.
    1880 
    1881 \subsubsection{Partial Signalling} \label{partial-sig}
    1882 Finally, the solution that is chosen for \CFA is to use partial signalling.
    1883 Again 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@.
    1884 Only when it reaches line \ref{line:lastRelease} does it actually wake up the waiting thread.
    1885 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.
    1886 This solution has a much simpler implementation than a dependency graph solving algorithms, which is why it was chosen.
    1887 Furthermore, after being fully implemented, this solution does not appear to have any significant downsides.
    1888 
    1889 Using 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]
    1906 monitor DatingService {
    1907         // compatibility codes
    1908         enum{ CCodes = 20 };
    1909 
    1910         int girlPhoneNo
    1911         int boyPhoneNo;
    1912 };
    1913 
    1914 condition girls[CCodes];
    1915 condition boys [CCodes];
    1916 condition exchange;
    1917 
    1918 int 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 }
    1931 int boy(int phoneNo, int cfa) {
    1932         // same as above
    1933         // with boy/girl interchanged
    1934 }
    1935 \end{cfa}&\begin{cfa}[tabsize=3]
    1936 monitor DatingService {
    1937 
    1938         enum{ CCodes = 20 };    // compatibility codes
    1939 
    1940         int girlPhoneNo;
    1941         int boyPhoneNo;
    1942 };
    1943 
    1944 condition girls[CCodes];
    1945 condition boys [CCodes];
    1946 // exchange is not needed
    1947 
    1948 int 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 
    1964 int 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}
    1973 An important note is that, until now, signalling a monitor was a delayed operation.
    1974 The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the @signal@ statement.
    1975 However, 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 
    1977 The example in table \ref{tbl:datingservice} highlights the difference in behaviour.
    1978 As mentioned, @signal@ only transfers ownership once the current critical section exits; this behaviour requires additional synchronization when a two-way handshake is needed.
    1979 To avoid this explicit synchronization, the @condition@ type offers the @signal_block@ routine, which handles the two-way handshake as shown in the example.
    1980 This feature removes the need for a second condition variables and simplifies programming.
    1981 Like 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 % ======================================================================
     1853\end{comment}
     1854
     1855
     1856\begin{comment}
    19851857\section{External scheduling} \label{extsched}
    1986 % ======================================================================
    1987 % ======================================================================
    1988 An alternative to internal scheduling is external scheduling (see Table~\ref{tbl:sched}).
     1858
    19891859\begin{table}
    19901860\begin{tabular}{|c|c|c|}
     
    20501920\label{tbl:sched}
    20511921\end{table}
    2052 This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
    2053 Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
    2054 External 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).
    2055 Of 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.
    2056 Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multiple-monitor routines.
    2057 The previous example shows a simple use @_Accept@ versus @wait@/@signal@ and its advantages.
    2058 Note 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.
    20591922
    20601923For 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.
    20611924On the other hand, external scheduling guarantees that while routine @P@ is waiting, no other routine than @V@ can acquire the monitor.
    2062 
    2063 % ======================================================================
    2064 % ======================================================================
     1925\end{comment}
     1926
     1927
    20651928\subsection{Loose Object Definitions}
    2066 % ======================================================================
    2067 % ======================================================================
    2068 In \uC, a monitor class declaration includes an exhaustive list of monitor operations.
    2069 Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
    2070 
    2071 \begin{cfa}
    2072 monitor A {};
    2073 
    2074 void f(A & mutex a);
    2075 void g(A & mutex a) {
    2076         waitfor(f); // Obvious which f() to wait for
    2077 }
    2078 
    2079 void f(A & mutex a, int); // New different F added in scope
    2080 void h(A & mutex a) {
    2081         waitfor(f); // Less obvious which f() to wait for
    2082 }
    2083 \end{cfa}
    2084 
    2085 Furthermore, external scheduling is an example where implementation constraints become visible from the interface.
    2086 Here 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}
     1929\label{s:LooseObjectDefinitions}
     1930
     1931In an object-oriented programming-language, a class includes an exhaustive list of operations.
     1932However, new members can be added via static inheritance or dynaic members, \eg JavaScript~\cite{JavaScript}.
     1933Similarly, monitor routines can be added at any time in \CFA, making it less clear for programmers and more difficult to implement.
     1934\begin{cfa}
     1935monitor M {};
     1936void `f`( M & mutex m );
     1937void g( M & mutex m ) { waitfor( `f` ); }       $\C{// clear which f}$
     1938void `f`( M & mutex m, int );                           $\C{// different f}$
     1939void h( M & mutex m ) { waitfor( `f` ); }       $\C{// unclear which f}$
     1940\end{cfa}
     1941Hence, the cfa-code for the entering a monitor looks like:
     1942\begin{cfa}
     1943if ( $\textrm{\textit{monitor is free}}$ ) $\LstCommentStyle{// \color{red}enter}$
     1944else if ( $\textrm{\textit{already own monitor}}$ ) $\LstCommentStyle{// \color{red}continue}$
     1945else if ( $\textrm{\textit{monitor accepts me}}$ ) $\LstCommentStyle{// \color{red}enter}$
     1946else $\LstCommentStyle{// \color{red}block}$
     1947\end{cfa}
    21011948For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instructions.
    2102 However, a fast check for @monitor accepts me@ is much harder to implement depending on the constraints put on the monitors.
    2103 Indeed, monitors are often expressed as an entry queue and some acceptor queue as in Figure~\ref{fig:ClassicalMonitor}.
     1949However, a fast check for \emph{monitor accepts me} is much harder to implement depending on the constraints put on the monitors.
     1950Figure~\ref{fig:ClassicalMonitor} shows monitors are often expressed as an entry (calling) queue, some acceptor queues, and an urgent stack/queue.
    21041951
    21051952\begin{figure}
    21061953\centering
    2107 \subfloat[Classical Monitor] {
     1954\subfloat[Classical monitor] {
    21081955\label{fig:ClassicalMonitor}
    2109 {\resizebox{0.45\textwidth}{!}{\input{monitor}}}
     1956{\resizebox{0.45\textwidth}{!}{\input{monitor.pstex_t}}}
    21101957}% subfloat
    2111 \qquad
    2112 \subfloat[\textbf{bulk-acq} Monitor] {
     1958\quad
     1959\subfloat[Bulk acquire monitor] {
    21131960\label{fig:BulkMonitor}
    2114 {\resizebox{0.45\textwidth}{!}{\input{ext_monitor}}}
     1961{\resizebox{0.45\textwidth}{!}{\input{ext_monitor.pstex_t}}}
    21151962}% subfloat
    2116 \caption{External Scheduling Monitor}
     1963\caption{Monitor Implementation}
     1964\label{f:MonitorImplementation}
    21171965\end{figure}
    21181966
    2119 There are other alternatives to these pictures, but in the case of the left picture, implementing a fast accept check is relatively easy.
    2120 Restricted 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.
    2121 This approach requires a unique dense ordering of routines with an upper-bound and that ordering must be consistent across translation units.
    2122 For OO languages these constraints are common, since objects only offer adding member routines consistently across translation units via inheritance.
    2123 However, in \CFA users can extend objects with mutex routines that are only visible in certain translation unit.
    2124 This 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 
    2126 The alternative is to alter the implementation as in Figure~\ref{fig:BulkMonitor}.
    2127 Here, the mutex routine called is associated with a thread on the entry queue while a list of acceptable routines is kept separate.
    2128 Generating a mask dynamically means that the storage for the mask information can vary between calls to @waitfor@, allowing for more flexibility and extensions.
    2129 Storing an array of accepted function pointers replaces the single instruction bitmask comparison with dereferencing a pointer followed by a linear search.
    2130 Furthermore, 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 
     1967For 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.
     1968This approach requires a unique dense ordering of routines with a small upper-bound and the ordering must be consistent across translation units.
     1969For 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
     1971Figure~\ref{fig:BulkMonitor} shows the \CFA monitor implementation.
     1972The mutex routine called is associated with each thread on the entry queue, while a list of acceptable routines is kept separately.
     1973The 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}
    21321976\begin{figure}
    21331977\begin{cfa}[caption={Example of nested external scheduling},label={f:nest-ext}]
     
    21451989\end{figure}
    21461990
    2147 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 function pointer and a set of monitors, as is discussed in the next section.
     1991Note 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.
    21481992These details are omitted from the picture for the sake of simplicity.
    21491993
     
    21531997In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be  hard to write.
    21541998This 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.
    2155 
    2156 % ======================================================================
    2157 % ======================================================================
     1999\end{comment}
     2000
     2001
    21582002\subsection{Multi-Monitor Scheduling}
    2159 % ======================================================================
    2160 % ======================================================================
     2003\label{s:Multi-MonitorScheduling}
    21612004
    21622005External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax.
    2163 Even in the simplest possible case, some new semantics needs to be established:
     2006Even in the simplest possible case, new semantics needs to be established:
    21642007\begin{cfa}
    21652008monitor M {};
    2166 
    2167 void f(M & mutex a);
    2168 
    2169 void 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}
    2173 The obvious solution is to specify the correct monitor as follows:
    2174 
     2009void f( M & mutex m1 );
     2010void g( M & mutex m1, M & mutex m2 ) {
     2011        waitfor( f );                                                   $\C{// pass m1 or m2 to f?}$
     2012}
     2013\end{cfa}
     2014The 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}
     2018Routine @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@).
     2019This behaviour can be extended to the multi-monitor @waitfor@ statement.
    21752020\begin{cfa}
    21762021monitor M {};
    2177 
    2178 void f(M & mutex a);
    2179 
    2180 void g(M & mutex a, M & mutex b) {
    2181         // wait for call to f with argument b
    2182         waitfor(f, b);
    2183 }
    2184 \end{cfa}
    2185 This syntax is unambiguous.
    2186 Both locks are acquired and kept by @g@.
    2187 When routine @f@ is called, the lock for monitor @b@ is temporarily transferred from @g@ to @f@ (while @g@ still holds lock @a@).
    2188 This behaviour can be extended to the multi-monitor @waitfor@ statement as follows.
    2189 
    2190 \begin{cfa}
    2191 monitor M {};
    2192 
    2193 void f(M & mutex a, M & mutex b);
    2194 
    2195 void 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 
    2201 Note 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.
     2022void f( M & mutex m1, M & mutex m2 );
     2023void 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}
     2027Again, the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired by accepting routine.
    22022028
    22032029An important behaviour to note is when a set of monitors only match partially:
    2204 
    22052030\begin{cfa}
    22062031mutex struct A {};
    2207 
    22082032mutex struct B {};
    2209 
    2210 void g(A & mutex a, B & mutex b) {
    2211         waitfor(f, a, b);
    2212 }
    2213 
     2033void g( A & mutex m1, B & mutex m2 ) {
     2034        waitfor( f, m1, m2 );
     2035}
    22142036A a1, a2;
    22152037B b;
    2216 
    22172038void foo() {
    2218         g(a1, b); // block on accept
    2219 }
    2220 
     2039        g( a1, b ); // block on accept
     2040}
    22212041void bar() {
    2222         f(a2, b); // fulfill cooperation
     2042        f( a2, b ); // fulfill cooperation
    22232043}
    22242044\end{cfa}
     
    22272047It 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.
    22282048
    2229 % ======================================================================
    2230 % ======================================================================
     2049
    22312050\subsection{\protect\lstinline|waitfor| Semantics}
    2232 % ======================================================================
    2233 % ======================================================================
    2234 
    2235 Syntactically, the @waitfor@ statement takes a function identifier and a set of monitors.
    2236 While 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.
    2237 It checks that the set of monitors passed in matches the requirements for a function call.
     2051
     2052Syntactically, the @waitfor@ statement takes a routine identifier and a set of monitors.
     2053While 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.
     2054It checks that the set of monitors passed in matches the requirements for a routine call.
    22382055Figure~\ref{f:waitfor} shows various usages of the waitfor statement and which are acceptable.
    2239 The choice of the function type is made ignoring any non-@mutex@ parameter.
     2056The choice of the routine type is made ignoring any non-@mutex@ parameter.
    22402057One limitation of the current implementation is that it does not handle overloading, but overloading is possible.
    22412058\begin{figure}
     
    22632080        waitfor(f2, a1, a2); // Incorrect : Mutex arguments don't match
    22642081        waitfor(f1, 1);      // Incorrect : 1 not a mutex argument
    2265         waitfor(f9, a1);     // Incorrect : f9 function does not exist
     2082        waitfor(f9, a1);     // Incorrect : f9 routine does not exist
    22662083        waitfor(*fp, a1 );   // Incorrect : fp not an identifier
    22672084        waitfor(f4, a1);     // Incorrect : f4 ambiguous
     
    22732090
    22742091Finally, for added flexibility, \CFA supports constructing a complex @waitfor@ statement using the @or@, @timeout@ and @else@.
    2275 Indeed, 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.
    2276 To 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.
    2277 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 function call already arrived and otherwise continues.
     2092Indeed, 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.
     2093To 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.
     2094A @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.
    22782095Any 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.
    22792096Figure~\ref{f:waitfor2} demonstrates several complex masks and some incorrect ones.
     
    23302147\end{figure}
    23312148
    2332 % ======================================================================
    2333 % ======================================================================
     2149
    23342150\subsection{Waiting For The Destructor}
    2335 % ======================================================================
    2336 % ======================================================================
     2151
    23372152An interesting use for the @waitfor@ statement is destructor semantics.
    23382153Indeed, the @waitfor@ statement can accept any @mutex@ routine, which includes the destructor (see section \ref{data}).
     
    23612176
    23622177
    2363 % ######     #    ######     #    #       #       ####### #       ###  #####  #     #
    2364 % #     #   # #   #     #   # #   #       #       #       #        #  #     # ##   ##
    2365 % #     #  #   #  #     #  #   #  #       #       #       #        #  #       # # # #
    2366 % ######  #     # ######  #     # #       #       #####   #        #   #####  #  #  #
    2367 % #       ####### #   #   ####### #       #       #       #        #        # #     #
    2368 % #       #     # #    #  #     # #       #       #       #        #  #     # #     #
    2369 % #       #     # #     # #     # ####### ####### ####### ####### ###  #####  #     #
    23702178\section{Parallelism}
     2179
    23712180Historically, computer performance was about processor speeds and instruction counts.
    23722181However, with heat dissipation being a direct consequence of speed increase, parallelism has become the new source for increased performance~\cite{Sutter05, Sutter05b}.
     
    23782187While 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.
    23792188
     2189
    23802190\section{Paradigms}
     2191
     2192
    23812193\subsection{User-Level Threads}
     2194
    23822195A direct improvement on the \textbf{kthread} approach is to use \textbf{uthread}.
    23832196These threads offer most of the same features that the operating system already provides but can be used on a much larger scale.
     
    23882201Examples of languages that support \textbf{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    23892202
     2203
    23902204\subsection{Fibers : User-Level Threads Without Preemption} \label{fibers}
     2205
    23912206A popular variant of \textbf{uthread} is what is often referred to as \textbf{fiber}.
    23922207However, \textbf{fiber} do not present meaningful semantic differences with \textbf{uthread}.
     
    23972212An example of a language that uses fibers is Go~\cite{Go}
    23982213
     2214
    23992215\subsection{Jobs and Thread Pools}
     2216
    24002217An approach on the opposite end of the spectrum is to base parallelism on \textbf{pool}.
    24012218Indeed, \textbf{pool} offer limited flexibility but at the benefit of a simpler user interface.
     
    24082225The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    24092226
     2227
    24102228\subsection{Paradigm Performance}
     2229
    24112230While 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.
    24122231Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload.
     
    24162235Finally, if the units of uninterrupted work are large, enough the paradigm choice is largely amortized by the actual work done.
    24172236
     2237
    24182238\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
     2239
    24192240A \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}.
    24202241It 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.
     
    24242245Currently \CFA only supports one \textbf{cfacluster}, the initial one.
    24252246
     2247
    24262248\subsection{Future Work: Machine Setup}\label{machine}
     2249
    24272250While this was not done in the context of this paper, another important aspect of clusters is affinity.
    24282251While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heterogeneous setups.
     
    24302253OS 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.
    24312254
     2255
    24322256\subsection{Paradigms}\label{cfaparadigms}
     2257
    24332258Given these building blocks, it is possible to reproduce all three of the popular paradigms.
    24342259Indeed, \textbf{uthread} is the default paradigm in \CFA.
     
    24382263
    24392264
    2440 
    24412265\section{Behind the Scenes}
     2266
    24422267There are several challenges specific to \CFA when implementing concurrency.
    2443 These challenges are a direct result of \textbf{bulk-acq} and loose object definitions.
     2268These challenges are a direct result of bulk acquire and loose object definitions.
    24442269These two constraints are the root cause of most design decisions in the implementation.
    24452270Furthermore, to avoid contention from dynamically allocating memory in a concurrent environment, the internal-scheduling design is (almost) entirely free of mallocs.
     
    24492274The main memory concern for concurrency is queues.
    24502275All 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.
    2451 Since 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.
     2276Since 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.
    24522277Conveniently, 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.
    24532278Since 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.
    24542279The 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.
    24552280
    2456 Note 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 % ======================================================================
     2281Note 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
    24602284\section{Mutex Routines}
    2461 % ======================================================================
    2462 % ======================================================================
    24632285
    24642286The first step towards the monitor implementation is simple @mutex@ routines.
     
    24952317\end{figure}
    24962318
     2319
    24972320\subsection{Details: Interaction with polymorphism}
     2321
    24982322Depending 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.
    24992323However, it is shown that entry-point locking solves most of the issues.
     
    25642388void foo(T * mutex t);
    25652389
    2566 // Correct: this function only works on monitors (any monitor)
     2390// Correct: this routine only works on monitors (any monitor)
    25672391forall(dtype T | is_monitor(T))
    25682392void bar(T * mutex t));
     
    25712395Both entry point and \textbf{callsite-locking} are feasible implementations.
    25722396The 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.
    2573 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 function body.
     2397It 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.
    25742398For example, the monitor call can appear in the middle of an expression.
    25752399Furthermore, 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.
    25762400
    2577 % ======================================================================
    2578 % ======================================================================
     2401
    25792402\section{Threading} \label{impl:thread}
    2580 % ======================================================================
    2581 % ======================================================================
    25822403
    25832404Figure \ref{fig:system1} shows a high-level picture if the \CFA runtime system in regards to concurrency.
     
    25922413\end{figure}
    25932414
     2415
    25942416\subsection{Processors}
     2417
    25952418Parallelism 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.
    25962419Indeed, any parallelism must go through operating-system libraries.
     
    26002423Processors internally use coroutines to take advantage of the existing context-switching semantics.
    26012424
     2425
    26022426\subsection{Stack Management}
     2427
    26032428One of the challenges of this system is to reduce the footprint as much as possible.
    26042429Specifically, all @pthread@s created also have a stack created with them, which should be used as much as possible.
     
    26072432In 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.
    26082433
     2434
    26092435\subsection{Context Switching}
     2436
    26102437As 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.
    2611 To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific function call.
     2438To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific routine call.
    26122439This 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.
    2613 Note that the instruction pointer can be left untouched since the context-switch is always inside the same function.
     2440Note that the instruction pointer can be left untouched since the context-switch is always inside the same routine
    26142441Threads, however, do not context-switch between each other directly.
    26152442They context-switch to the scheduler.
     
    26212448This option is not currently present in \CFA, but the changes required to add it are strictly additive.
    26222449
     2450
    26232451\subsection{Preemption} \label{preemption}
     2452
    26242453Finally, an important aspect for any complete threading system is preemption.
    26252454As 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.
     
    26482477As a result, a signal handler can start on one kernel thread and terminate on a second kernel thread (but the same user thread).
    26492478It 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.
    2650 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'' functions from other functions.}.
     2479This 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}.
    26512480However, since the kernel thread handling preemption requires a different signal mask, executing user threads on the kernel-alarm thread can cause deadlocks.
    26522481For this reason, the alarm thread is in a tight loop around a system call to @sigwaitinfo@, requiring very little CPU time for preemption.
     
    26552484Indeed, @sigwait@ can differentiate signals sent from @pthread_sigqueue@ from signals sent from alarms or the kernel.
    26562485
     2486
    26572487\subsection{Scheduler}
    26582488Finally, an aspect that was not mentioned yet is the scheduling algorithm.
     
    26602490Further discussion on scheduling is present in section \ref{futur:sched}.
    26612491
    2662 % ======================================================================
    2663 % ======================================================================
     2492
    26642493\section{Internal Scheduling} \label{impl:intsched}
    2665 % ======================================================================
    2666 % ======================================================================
     2494
    26672495The following figure is the traditional illustration of a monitor (repeated from page~\pageref{fig:ClassicalMonitor} for convenience):
    26682496
    26692497\begin{figure}
    26702498\begin{center}
    2671 {\resizebox{0.4\textwidth}{!}{\input{monitor}}}
     2499{\resizebox{0.4\textwidth}{!}{\input{monitor.pstex_t}}}
    26722500\end{center}
    26732501\caption{Traditional illustration of a monitor}
     
    26782506
    26792507For \CFA, this picture does not have support for blocking multiple monitors on a single condition.
    2680 To support \textbf{bulk-acq} two changes to this picture are required.
     2508To support bulk acquire two changes to this picture are required.
    26812509First, it is no longer helpful to attach the condition to \emph{a single} monitor.
    26822510Secondly, the thread waiting on the condition has to be separated across multiple monitors, seen in figure \ref{fig:monitor_cfa}.
     
    27272555\end{figure}
    27282556
    2729 The solution discussed in \ref{intsched} can be seen in the exit routine of listing \ref{f:entry2}.
     2557The solution discussed in \ref{s:InternalScheduling} can be seen in the exit routine of listing \ref{f:entry2}.
    27302558Basically, 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.
    27312559This solution is deadlock safe as well as preventing any potential barging.
     
    29632791}
    29642792\end{cfa}
    2965 This function is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
     2793This routine is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
    29662794However, 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}
    29672795\begin{figure}
     
    31482976For monitors, the simplest approach is to measure how long it takes to enter and leave a monitor routine.
    31492977Figure~\ref{f:mutex} shows the code for \CFA.
    3150 To 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.
     2978To 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.
    31512979The results can be shown in table \ref{tab:mutex}.
    31522980
     
    33993227Therefore, there is still significant work to improve performance.
    34003228Many of the data structures and algorithms may change in the future to more efficient versions.
    3401 For example, the number of monitors in a single \textbf{bulk-acq} is only bound by the stack size, this is probably unnecessarily generous.
     3229For example, the number of monitors in a single bulk acquire is only bound by the stack size, this is probably unnecessarily generous.
    34023230It may be possible that limiting the number helps increase performance.
    34033231However, it is not obvious that the benefit would be significant.
  • TabularUnified doc/papers/concurrency/figures/ext_monitor.fig

    r0182bfa r28f3a19  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 3450.000 3150 3150 2850 3450 3150 3750
    11 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 4350.000 3150 4050 2850 4350 3150 4650
    12 6 5850 1950 6150 2250
    13 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2100 105 105 6000 2100 6105 2205
    14 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1575.000 3450.000 1575 3150 1275 3450 1575 3750
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1575.000 4350.000 1575 4050 1275 4350 1575 4650
     126 4275 1950 4575 2250
     131 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2100 105 105 4425 2100 4530 2205
     144 1 -1 0 0 0 10 0.0000 2 105 90 4425 2160 d\001
    1515-6
    16 6 5100 2100 5400 2400
    17 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
    18 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
     166 4275 1650 4575 1950
     171 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 1800 105 105 4425 1800 4530 1905
     184 1 -1 0 0 0 10 0.0000 2 105 90 4425 1860 b\001
    1919-6
    20 6 5100 1800 5400 2100
    21 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 1950 105 105 5250 1950 5355 1950
    22 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
     206 1495 5445 5700 5655
     211 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1575 5550 80 80 1575 5550 1655 5630
     221 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2925 5550 105 105 2925 5550 3030 5655
     231 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4425 5550 105 105 4425 5550 4530 5655
     244 0 -1 0 0 0 12 0.0000 2 135 1035 3150 5625 blocked task\001
     254 0 -1 0 0 0 12 0.0000 2 135 870 1725 5625 active task\001
     264 0 -1 0 0 0 12 0.0000 2 135 1050 4650 5625 routine mask\001
    2327-6
    24 6 5850 1650 6150 1950
    25 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
    26 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     286 3525 1800 3825 2400
     291 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3675 1950 105 105 3675 1950 3780 1950
     302 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
     324 1 4 0 0 0 10 0.0000 2 105 120 3675 2010 Y\001
    2733-6
    28 6 3070 5445 7275 5655
    29 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
    30 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
    31 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 6000 5550 105 105 6000 5550 6105 5655
    32 4 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
    33 4 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
    34 4 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
     346 3525 2100 3825 2400
     351 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3675 2250 105 105 3675 2250 3780 2250
     364 1 4 0 0 0 10 0.0000 2 105 120 3675 2295 X\001
    3537-6
    36 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
    37 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 3600 105 105 3600 3600 3705 3705
    38 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 3900 105 105 6600 3900 6705 4005
    39 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 3900 105 105 6900 3900 7005 4005
    40 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2700 105 105 6000 2700 6105 2805
    41 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2400 105 105 6000 2400 6105 2505
    42 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 5100 4575 80 80 5100 4575 5180 4655
     381 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1725 3600 105 105 1725 3600 1830 3705
     391 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2025 3600 105 105 2025 3600 2130 3705
     401 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5025 3900 105 105 5025 3900 5130 4005
     411 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5325 3900 105 105 5325 3900 5430 4005
     421 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2700 105 105 4425 2700 4530 2805
     431 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4425 2400 105 105 4425 2400 4530 2505
     441 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3525 4575 80 80 3525 4575 3605 4655
    43452 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    44          4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
     46         2475 2925 3900 2925 3900 3225 2475 3225 2475 2925
    45472 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
     48         1575 3750 2175 3750 2175 4050 1575 4050
    47492 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    48          3150 3450 3750 3450 3900 3675
     50         1575 3450 2175 3450 2325 3675
    49512 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    50          3750 3150 3600 3375
     52         2175 3150 2025 3375
    51532 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    52          3150 4350 3750 4350 3900 4575
     54         1575 4350 2175 4350 2325 4575
    53552 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    54          3750 4050 3600 4275
     56         2175 4050 2025 4275
    55572 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
     58         1575 4650 2175 4650 2175 4950 3375 4950
    57592 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    58          6450 3750 6300 3975
     60         4875 3750 4725 3975
    59612 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    60          4950 4950 5175 5100
     62         3375 4950 3600 5100
    61632 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
     64         3675 4950 4875 4950 4875 4050 5475 4050 5475 3750 4875 3750
     65         4875 2850 4575 2850 4575 1650
    64662 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
    66 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
     67         4275 4200 4275 3300 2775 3300 2775 4200 4275 4200
     682 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    6769        1 1 1.00 60.00 120.00
    68         7 1 1.00 60.00 120.00
    69          5250 3150 5250 2400
     70         3675 3075 3675 2400
     712 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     72         4125 2850 4575 3000
    70732 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
    72 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    73          5700 2850 6150 3000
    74 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    75          5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
    76 4 1 -1 0 0 0 10 0.0000 2 75 75 6000 2745 a\001
    77 4 1 -1 0 0 0 10 0.0000 2 75 75 6000 2445 c\001
    78 4 1 -1 0 0 0 12 0.0000 2 135 315 5100 5325 exit\001
    79 4 1 -1 0 0 0 12 0.0000 2 135 135 3300 3075 A\001
    80 4 1 -1 0 0 0 12 0.0000 2 135 795 3300 4875 condition\001
    81 4 1 -1 0 0 0 12 0.0000 2 135 135 3300 5100 B\001
    82 4 0 -1 0 0 0 12 0.0000 2 135 420 6600 3675 stack\001
    83 4 0 -1 0 0 0 12 0.0000 2 180 750 6600 3225 acceptor/\001
    84 4 0 -1 0 0 0 12 0.0000 2 180 750 6600 3450 signalled\001
    85 4 1 -1 0 0 0 12 0.0000 2 135 795 3300 2850 condition\001
    86 4 1 -1 0 0 0 12 0.0000 2 165 420 6000 1350 entry\001
    87 4 1 -1 0 0 0 12 0.0000 2 135 495 6000 1575 queue\001
    88 4 0 -1 0 0 0 12 0.0000 2 135 525 6300 2400 arrival\001
    89 4 0 -1 0 0 0 12 0.0000 2 135 630 6300 2175 order of\001
    90 4 1 -1 0 0 0 12 0.0000 2 135 525 5100 3675 shared\001
    91 4 1 -1 0 0 0 12 0.0000 2 135 735 5100 3975 variables\001
    92 4 0 0 50 -1 0 11 0.0000 2 165 855 4275 3150 Acceptables\001
    93 4 0 0 50 -1 0 11 0.0000 2 120 165 5775 2700 W\001
    94 4 0 0 50 -1 0 11 0.0000 2 120 135 5775 2400 X\001
    95 4 0 0 50 -1 0 11 0.0000 2 120 105 5775 2100 Z\001
    96 4 0 0 50 -1 0 11 0.0000 2 120 135 5775 1800 Y\001
     74         1575 3150 2175 3150 2175 2850 4125 2850 4125 1650
     754 1 -1 0 0 0 10 0.0000 2 75 75 4425 2745 a\001
     764 1 -1 0 0 0 10 0.0000 2 75 75 4425 2445 c\001
     774 1 -1 0 0 0 12 0.0000 2 135 315 3525 5325 exit\001
     784 1 -1 0 0 0 12 0.0000 2 135 135 1725 3075 A\001
     794 1 -1 0 0 0 12 0.0000 2 135 795 1725 4875 condition\001
     804 1 -1 0 0 0 12 0.0000 2 135 135 1725 5100 B\001
     814 0 -1 0 0 0 12 0.0000 2 135 420 5025 3675 stack\001
     824 0 -1 0 0 0 12 0.0000 2 180 750 5025 3225 acceptor/\001
     834 0 -1 0 0 0 12 0.0000 2 180 750 5025 3450 signalled\001
     844 1 -1 0 0 0 12 0.0000 2 135 795 1725 2850 condition\001
     854 1 -1 0 0 0 12 0.0000 2 165 420 4425 1350 entry\001
     864 1 -1 0 0 0 12 0.0000 2 135 495 4425 1575 queue\001
     874 0 -1 0 0 0 12 0.0000 2 135 525 4725 2400 arrival\001
     884 0 -1 0 0 0 12 0.0000 2 135 630 4725 2175 order of\001
     894 1 -1 0 0 0 12 0.0000 2 135 525 3525 3675 shared\001
     904 1 -1 0 0 0 12 0.0000 2 135 735 3525 3975 variables\001
     914 0 4 50 -1 0 11 0.0000 2 120 135 4150 1875 Y\001
     924 0 4 50 -1 0 11 0.0000 2 120 105 4150 2175 Z\001
     934 0 4 50 -1 0 11 0.0000 2 120 135 4150 2475 X\001
     944 0 4 50 -1 0 11 0.0000 2 120 165 4150 2775 W\001
     954 0 -1 0 0 3 12 0.0000 2 150 540 5025 4275 urgent\001
     964 1 0 50 -1 0 11 0.0000 2 165 600 3150 3150 accepted\001
  • TabularUnified doc/papers/concurrency/figures/monitor.fig

    r0182bfa r28f3a19  
    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
    74 2 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
    76742 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
    7775         3600 4200 4800 4200 4800 3300 5400 3300 5400 3000 4800 3000
     
    79772 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    8078         4200 3450 4200 2550 2700 2550 2700 3450 4200 3450
     792 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 -1 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
    92 4 1 -1 0 0 0 12 0.0000 2 135 135 3450 1425 Y\001
     914 1 4 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
     924 1 4 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
     1024 0 -1 0 0 3 12 0.0000 2 150 540 4950 3525 urgent\001
  • TabularUnified doc/papers/general/Makefile

    r0182bfa r28f3a19  
    5959        dvips ${Build}/$< -o $@
    6060
    61 ${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 ../../bibliography/pl.bib
     61${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                ../../bibliography/pl.bib | ${Build}
    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
  • TabularUnified doc/papers/general/Paper.tex

    r0182bfa r28f3a19  
    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 commercial operating-systems to hobby projects.
     203The 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.
    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 commercial operating-systems to hobby projects.
     226The 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.
    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.
  • TabularUnified doc/proposals/ctordtor/Makefile

    r0182bfa r28f3a19  
    1 ## Define the appropriate configuration variables.
     1## Define the configuration variables.
    22
    3 MACROS = ../../LaTeXmacros
    4 BIB = ../../bibliography
     3Build = build
     4Figures = figures
     5Macros = ../../LaTeXmacros
     6Bib = ../../bibliography
    57
    6 TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
    7 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
     8TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
     9LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    810BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     11
     12MAKEFLAGS = --no-print-directory # --silent
     13VPATH = ${Build} ${Figures}
    914
    1015## Define the text source files.
     
    2934
    3035DOCUMENT = ctor.pdf
     36BASE = ${basename ${DOCUMENT}}
    3137
    3238# Directives #
     39
     40.PHONY : all clean                                      # not file names
    3341
    3442all : ${DOCUMENT}
    3543
    3644clean :
    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}
     45        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    3946
    4047# File Dependencies #
    4148
    42 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     49${DOCUMENT} : ${BASE}.ps
    4350        ps2pdf $<
    4451
    45 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    46         dvips $< -o $@
     52${BASE}.ps : ${BASE}.dvi
     53        dvips ${Build}/$< -o $@
    4754
    48 ${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
    49                 $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
    5057        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    51         if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
     58        #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
    5259        # Must have *.aux file containing citations for bibtex
    5360        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    54         -${BibTeX} ${basename $@}
    55         # Some citations reference others so run steps again to resolve these citations
     61        -${BibTeX} ${Build}/${basename $@}
     62        # Some citations reference others so run again to resolve these citations
    5663        ${LaTeX} ${basename $@}.tex
    57         -${BibTeX} ${basename $@}
     64        -${BibTeX} ${Build}/${basename $@}
    5865        # Make index from *.aux entries and input index at end of document
    59         makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
     66        #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
     67        # Run again to finish citations
    6068        ${LaTeX} ${basename $@}.tex
    6169        # Run again to get index title into table of contents
     
    6775## Define the default recipes.
    6876
    69 %.tex : %.fig
    70         fig2dev -L eepic $< > $@
     77${Build}:
     78        mkdir -p ${Build}
    7179
    72 %.ps : %.fig
    73         fig2dev -L ps $< > $@
     80%.tex : %.fig | ${Build}
     81        fig2dev -L eepic $< > ${Build}/$@
    7482
    75 %.pstex : %.fig
    76         fig2dev -L pstex $< > $@
    77         fig2dev -L pstex_t -p $@ $< > $@_t
     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
    7889
    7990# Local Variables: #
  • TabularUnified doc/proposals/ctordtor/ctor.tex

    r0182bfa r28f3a19  
    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 
    91\documentclass[twoside,11pt]{article}
    102
     
    157\usepackage{textcomp}
    168\usepackage[latin1]{inputenc}
     9
    1710\usepackage{fullpage,times,comment}
    1811\usepackage{epic,eepic}
    19 \usepackage{upquote}                                                                    % switch curled `'" to straight
     12\usepackage{upquote}                                    % switch curled `'" to straight
    2013\usepackage{calc}
    2114\usepackage{xspace}
    2215\usepackage{graphicx}
    23 \usepackage{varioref}                                                                   % extended references
    24 \usepackage{listings}                                                                   % format program code
    25 \usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
     16\usepackage{varioref}                                   % extended references
     17\usepackage{listings}                                   % format program code
     18\usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
    2619\usepackage{latexsym}                                   % \Box glyph
    2720\usepackage{mathptmx}                                   % better math font with "times"
     
    3427\renewcommand{\UrlFont}{\small\sf}
    3528
    36 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
     29\setlength{\topmargin}{-0.45in}                         % move running title into header
    3730\setlength{\headsep}{0.25in}
    3831
     
    4336
    4437\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
    4548
    4649\title{
     
    8386\thispagestyle{plain}
    8487\pagenumbering{arabic}
    85 
    8688
    8789
  • TabularUnified doc/proposals/tuples/Makefile

    r0182bfa r28f3a19  
    1 ## Define the appropriate configuration variables.
     1## Define the configuration variables.
    22
    3 MACROS = ../../LaTeXmacros
    4 BIB = ../../bibliography
     3Build = build
     4Figures = figures
     5Macros = ../../LaTeXmacros
     6Bib = ../../bibliography
    57
    6 TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
    7 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
     8TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
     9LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    810BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     11
     12MAKEFLAGS = --no-print-directory --silent #
     13VPATH = ${Build} ${Figures}
    914
    1015## Define the text source files.
     
    2934
    3035DOCUMENT = tuples.pdf
     36BASE = ${basename ${DOCUMENT}}
    3137
    3238# Directives #
     39
     40.PHONY : all clean                                      # not file names
    3341
    3442all : ${DOCUMENT}
    3543
    3644clean :
    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}
     45        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    3946
    4047# File Dependencies #
    4148
    42 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     49${DOCUMENT} : ${BASE}.ps
    4350        ps2pdf $<
    4451
    45 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    46         dvips $< -o $@
     52${BASE}.ps : ${BASE}.dvi
     53        dvips ${Build}/$< -o $@
    4754
    48 ${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
    49                 $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
    5057        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    51         if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
     58        #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
    5259        # Must have *.aux file containing citations for bibtex
    5360        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    54         -${BibTeX} ${basename $@}
    55         # Some citations reference others so run steps again to resolve these citations
     61        -${BibTeX} ${Build}/${basename $@}
     62        # Some citations reference others so run again to resolve these citations
    5663        ${LaTeX} ${basename $@}.tex
    57         -${BibTeX} ${basename $@}
     64        -${BibTeX} ${Build}/${basename $@}
    5865        # Make index from *.aux entries and input index at end of document
    59         makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
     66        #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
     67        # Run again to finish citations
    6068        ${LaTeX} ${basename $@}.tex
    6169        # Run again to get index title into table of contents
     
    6775## Define the default recipes.
    6876
    69 %.tex : %.fig
    70         fig2dev -L eepic $< > $@
     77${Build}:
     78        mkdir -p ${Build}
    7179
    72 %.ps : %.fig
    73         fig2dev -L ps $< > $@
     80%.tex : %.fig | ${Build}
     81        fig2dev -L eepic $< > ${Build}/$@
    7482
    75 %.pstex : %.fig
    76         fig2dev -L pstex $< > $@
    77         fig2dev -L pstex_t -p $@ $< > $@_t
     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
    7889
    7990# Local Variables: #
  • TabularUnified doc/proposals/tuples/tuples.tex

    r0182bfa r28f3a19  
    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 
    91\documentclass[twoside,11pt]{article}
    102
     
    157\usepackage{textcomp}
    168\usepackage[latin1]{inputenc}
     9
    1710\usepackage{fullpage,times,comment}
    1811\usepackage{epic,eepic}
    19 \usepackage{upquote}                                                                    % switch curled `'" to straight
     12\usepackage{upquote}                                    % switch curled `'" to straight
    2013\usepackage{calc}
    2114\usepackage{xspace}
    2215\usepackage{graphicx}
    23 \usepackage{varioref}                                                                   % extended references
    24 \usepackage{listings}                                                                   % format program code
    25 \usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
     16\usepackage{varioref}                                   % extended references
     17\usepackage{listings}                                   % format program code
     18\usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
    2619\usepackage{latexsym}                                   % \Box glyph
    2720\usepackage{mathptmx}                                   % better math font with "times"
     
    3427\renewcommand{\UrlFont}{\small\sf}
    3528
    36 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
     29\setlength{\topmargin}{-0.45in}                         % move running title into header
    3730\setlength{\headsep}{0.25in}
    3831
     
    4235
    4336\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
    4447
    4548\title{
  • TabularUnified doc/proposals/user_conversions.md

    r0182bfa r28f3a19  
    55There is also a set of _explicit_ conversions that are only allowed through a
    66cast expression.
    7 Based on Glen's notes on conversions [1], I propose that safe and unsafe
    8 conversions be expressed as constructor variants, though I make explicit
    9 (cast) conversions a constructor variant as well rather than a dedicated
    10 operator.
     7I propose that safe, unsafe, and explicit (cast) conversions be expressed as
     8constructor variants.
    119Throughout this article, I will use the following operator names for
    1210constructors and conversion functions from `From` to `To`:
    1311
    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 
    22 Glen's design made no distinction between constructors and unsafe implicit
     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
     18It has been suggested that all constructors would define unsafe implicit
    2319conversions; this is elegant, but interacts poorly with tuples.
    2420Essentially, without making this distinction, a constructor like the following
     
    2622multiplying the space of possible interpretations of all functions:
    2723
    28         void ?{}( Coord *this, int x, int y );
     24        void ?{}( Coord& this, int x, int y );
    2925
    3026That said, it would certainly be possible to make a multiple-argument implicit
     
    3228used infrequently:
    3329
    34         void ?{unsafe}( Coord *this, int x, int y );
     30        void ?{unsafe}( Coord& this, int x, int y );
    3531
    3632An alternate possibility would be to only count two-arg constructors
    37 `void ?{} ( To*, From )` as unsafe conversions; under this semantics, safe and
     33`void ?{} ( To&, From )` as unsafe conversions; under this semantics, safe and
    3834explicit conversions should also have a compiler-enforced restriction to
    3935ensure that they are two-arg functions (this restriction may be valuable
     
    4339is convertable to `To`.
    4440If user-defined conversions are not added to the language,
    45 `void ?{} ( To*, From )` may be a suitable representation, relying on
     41`void ?{} ( To&, From )` may be a suitable representation, relying on
    4642conversions on the argument types to account for transitivity.
    47 On the other hand, `To*` should perhaps match its target type exactly, so
    48 another assertion syntax specific to conversions may be required, e.g.
    49 `From -> To`.
     43Since `To&` should be an exact match on `To`, this should put all the implicit
     44conversions on the RHS.
     45On the other hand, under some models (like [1]), implicit conversions are not
     46allowed in assertion parameters, so another assertion syntax specific to
     47conversions may be required, e.g. `From -> To`.
     48It has also been suggested that, for programmer control, no implicit
     49conversions (except, possibly, for polymorphic specialization) should be
     50allowed in resolution of cast operators.
     51
     52[1] ../working/assertion_resolution.md
    5053
    5154### Constructor Idiom ###
     
    5356that we can use the full range of Cforall features for conversions, including
    5457polymorphism.
    55 Glen [1] defines a _constructor idiom_ that can be used to create chains of
    56 safe conversions without duplicating code; given a type `Safe` which members
    57 of another type `From` can be directly converted to, the constructor idiom
    58 allows 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 ) {
     58In an earlier version of this proposal, Glen Ditchfield defines a
     59_constructor idiom_ that can be used to create chains of safe conversions
     60without 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
     62a 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 ) {
    6266                Safe tmp = /* some expression involving that */;
    63                 *this = tmp; // uses assertion parameter
     67                this{ tmp }; // initialize from assertion parameter
    6468        }
    6569
     
    6771unsafe conversions.
    6872
     73Glen's original suggestion said the copy constructor for `To` should also be
     74accepted as a resolution for `void ?{safe}( To&, Safe )` (`Safe` == `To`),
     75allowing this same code to be used for the single-step conversion as well.
     76This proposal does come at the cost of an extra copy initialization of the
     77target value, though.
     78
     79Contrariwise, if a monomorphic conversion from `From` to `Safe` is written,
     80e.g:
     81
     82        void ?{safe}( Safe& this, From that ) {
     83                this{ /* some parameters involving that */ };
     84        }
     85
     86Then the code for a transitive conversion from `From` to any `To` type
     87convertable 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
     95Given the entirely-boilerplate nature of this code, but negative performance
     96implications of the unmodified constructor idiom, it might be fruitful to have
     97transitive and single step conversion operators, and let CFA build the
     98transitive 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
    69103What selective non-use of the constructor idiom gives us is the ability to
    70104define a conversion that may only be the *last* conversion in a chain of such.
    71 Constructing a conversion graph able to unambiguously represent the full
    72 hierarchy of implicit conversions in C is provably impossible using only
    73 single-step conversions with no additional information (see Appendix A), but
    74 this mechanism is sufficiently powerful (see [1], though the design there has
    75 some minor bugs; the general idea is to use the constructor idiom to define
    76 two chains of conversions, one among the signed integral types, another among
    77 the unsigned, and to use monomorphic conversions to allow conversions between
    78 signed and unsigned integer types).
     105One use for this is to solve the problem that `explicit` conversions were
     106added to C++ for, that of conversions to `bool` chaining to become conversions
     107to any arithmetic type.
     108Another use is to unambiguously represent the full hierarchy of implicit
     109conversions in C by making sign conversions non-transitive, allowing the
     110compiler to resolve e.g. `int -> unsigned long` as
     111`int -> long -> unsigned long` over `int -> unsigned int -> unsigned long`.
     112See [2] for more details.
     113
     114[2] ../working/glen_conversions/index.html#usual
    79115
    80116### Appendix A: Partial and Total Orders ###
     
    153189convert from `int` to `unsigned long`, so we just put in a direct conversion
    154190and make the compiler smart enough to figure out the costs" - this is the
    155 approach taken by the existing compipler, but given that in a user-defined
     191approach taken by the existing compiler, but given that in a user-defined
    156192conversion proposal the users can build an arbitrary graph of conversions,
    157193this case still needs to be handled.
     
    160196exists a chain of conversions from `a` to `b` (see Appendix A for description
    161197of preorders and related constructs).
    162 This preorder corresponds roughly to a more usual type-theoretic concept of
     198This preorder roughly corresponds to a more usual type-theoretic concept of
    163199subtyping ("if I can convert `a` to `b`, `a` is a more specific type than
    164200`b`"); however, since this graph is arbitrary, it may contain cycles, so if
     
    192228and so is considered to be the nearer type.
    193229By transitivity, then, the conversion from `X` to `Y2` should be cheaper than
    194 the conversion from `X` to `W`, but in this case the `X` and `W` are
     230the conversion from `X` to `W`, but in this case the `Y2` and `W` are
    195231incomparable by the conversion preorder, so the tie is broken by the shorter
    196232path from `X` to `W` in favour of `W`, contradicting the transitivity property
  • TabularUnified doc/refrat/Makefile

    r0182bfa r28f3a19  
    5353        dvips ${Build}/$< -o $@
    5454
    55 ${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
    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
  • TabularUnified doc/theses/aaron_moss/comp_II/Makefile

    r0182bfa r28f3a19  
    3232
    3333DOCUMENT = comp_II.pdf
     34BASE = ${basename ${DOCUMENT}}
    3435
    3536# Directives #
     
    4041
    4142clean :
    42         @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
     43        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    4344
    4445# File Dependencies #
    4546
    46 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     47${DOCUMENT} : ${BASE}.ps
    4748        ps2pdf $<
    4849
    49 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     50${BASE}.ps : ${BASE}.dvi
    5051        dvips ${Build}/$< -o $@
    5152
    52 ${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    53                 ${Macros}/common.tex ${Macros}/indexstyle ../../../bibliography/pl.bib
     53${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     54                ${Macros}/common.tex ${Macros}/indexstyle ../../../bibliography/pl.bib | ${Build}
    5455        # Must have *.aux file containing citations for bibtex
    5556        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6667        mkdir -p ${Build}
    6768
    68 %.tex : %.fig
     69%.tex : %.fig ${Build}
    6970        fig2dev -L eepic $< > ${Build}/$@
    7071
    71 %.ps : %.fig
     72%.ps : %.fig | ${Build}
    7273        fig2dev -L ps $< > ${Build}/$@
    7374
    74 %.pstex : %.fig
     75%.pstex : %.fig | ${Build}
    7576        fig2dev -L pstex $< > ${Build}/$@
    7677        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • TabularUnified doc/theses/thierry_delisle/.gitignore

    r0182bfa r28f3a19  
    2525*.pdf
    2626*.png
     27*.ps
    2728figures/*.tex
    2829
  • TabularUnified doc/theses/thierry_delisle/Makefile

    r0182bfa r28f3a19  
    5151
    5252DOCUMENT = thesis.pdf
     53BASE = ${basename ${DOCUMENT}}
    5354
    5455# Directives #
     
    5960
    6061clean :
    61         @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
     62        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    6263
    6364# File Dependencies #
    6465
    65 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     66${DOCUMENT} : ${BASE}.ps
    6667        ps2pdf $<
    6768
    68 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     69${BASE}.ps : ${BASE}.dvi
    6970        dvips ${Build}/$< -o $@
    7071
    71 ${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    72                 ${Macros}/common.tex ${Macros}/indexstyle annex/local.bib ../../bibliography/pl.bib
     72${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     73                ${Macros}/common.tex ${Macros}/indexstyle annex/local.bib ../../bibliography/pl.bib | ${Build}
    7374        # Must have *.aux file containing citations for bibtex
    7475        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    8889        mkdir -p ${Build}
    8990
    90 %.tex : %.fig
     91%.tex : %.fig ${Build}
    9192        fig2dev -L eepic $< > ${Build}/$@
    9293
    93 %.ps : %.fig
     94%.ps : %.fig | ${Build}
    9495        fig2dev -L ps $< > ${Build}/$@
    9596
    96 %.pstex : %.fig
     97%.pstex : %.fig | ${Build}
    9798        fig2dev -L pstex $< > ${Build}/$@
    9899        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     
    101102# Tools to generate png files
    102103# to create a png we create a pdf and convert it to png
    103 %.png : build/%.pstex figures/%.tex
     104%.png : build/%.pstex figures/%.tex ${Build}
    104105        echo ${basename $@}
    105106        ${LaTeX} figures/${basename $@}.tex
     
    109110
    110111# creating a pdf of a figure requires generating some latex that just includes the figure
    111 figures/%.tex: build/%.pstex
     112figures/%.tex: build/%.pstex ${Build}
    112113        echo -n         "\documentclass[preview]{standalone}\n"         \
    113114                        "\usepackage[T1]{fontenc}\n"                    \
  • TabularUnified doc/user/Makefile

    r0182bfa r28f3a19  
    5757        dvips ${Build}/$< -o $@
    5858
    59 ${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    60                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
     59${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     60                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
    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
  • TabularUnified src/CodeGen/CodeGenerator.cc

    r0182bfa r28f3a19  
    133133                output << "__attribute__ ((";
    134134                for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
    135                         output << (*attr)->get_name();
    136                         if ( ! (*attr)->get_parameters().empty() ) {
     135                        output << (*attr)->name;
     136                        if ( ! (*attr)->parameters.empty() ) {
    137137                                output << "(";
    138                                 genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
     138                                genCommaList( (*attr)->parameters.begin(), (*attr)->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;
    174176                extension( functionDecl );
    175177                genAttributes( functionDecl->get_attributes() );
     
    185187                        functionDecl->get_statements()->accept( *visitor );
    186188                } // if
     189                if ( functionDecl->isDeleted ) {
     190                        output << " = void";
     191                }
    187192        }
    188193
    189194        void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
     195                // deleted decls should never be used, so don't print them
     196                if ( objectDecl->isDeleted && genC ) return;
    190197                if (objectDecl->get_name().empty() && genC ) {
    191198                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
     
    206213                        objectDecl->get_init()->accept( *visitor );
    207214                } // if
     215                if ( objectDecl->isDeleted ) {
     216                        output << " = void";
     217                }
    208218
    209219                if ( objectDecl->get_bitfieldWidth() ) {
     
    827837                expr->expr->accept( *visitor );
    828838        }
     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
    829867
    830868        // *** Statements
  • TabularUnified src/CodeGen/CodeGenerator.h

    r0182bfa r28f3a19  
    9494                void postvisit( ConstructorExpr * );
    9595                void postvisit( DeletedExpr * );
     96                void postvisit( DefaultArgExpr * );
     97                void postvisit( GenericExpr * );
    9698
    9799                //*** Statements
  • TabularUnified src/Common/Debug.h

    r0182bfa r28f3a19  
    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::Compiler ) {
     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 ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
  • TabularUnified src/Common/PassVisitor.h

    r0182bfa r28f3a19  
    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;
    127129
    128130        virtual void visit( VoidType * basicType ) override final;
     
    225227        virtual Expression * mutate( InitExpr *  initExpr ) override final;
    226228        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
     229        virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
     230        virtual Expression * mutate( GenericExpr * genExpr ) override final;
    227231
    228232        virtual Type * mutate( VoidType * basicType ) override final;
     
    258262
    259263private:
     264        bool inFunction = false;
     265
    260266        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    261267        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     
    313319        void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    314320        void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
    315         void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith     ( pass, 0, exprs, withStmt ); }
     321        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
    316322
    317323
  • TabularUnified src/Common/PassVisitor.impl.h

    r0182bfa r28f3a19  
    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;
    406410                        maybeAccept_impl( node->statements, *this );
    407411                        maybeAccept_impl( node->attributes, *this );
     
    434438                        indexerAddId( func );
    435439                        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;
    436444                        maybeMutate_impl( node->statements, *this );
    437445                        maybeMutate_impl( node->attributes, *this );
     
    712720        VISIT_START( node );
    713721        {
    714                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     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(); } );
    715725                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     726                inFunction = false;
    716727                visitStatementList( node->kids );
    717728        }
     
    723734        MUTATE_START( node );
    724735        {
    725                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     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(); } );
    726739                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     740                inFunction = false;
    727741                mutateStatementList( node->kids );
    728742        }
     
    828842        VISIT_START( node );
    829843
    830         visitExpression( node->condition );
    831         node->body = visitStatement( node->body );
     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        }
    832851
    833852        VISIT_END( node );
     
    838857        MUTATE_START( node );
    839858
    840         node->condition = mutateExpression( node->condition );
    841         node->body      = mutateStatement ( node->body      );
     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
    842867
    843868        MUTATE_END( Statement, node );
     
    20742099
    20752100//--------------------------------------------------------------------------
     2101// DefaultArgExpr
     2102template< typename pass_type >
     2103void 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
     2112template< typename pass_type >
     2113Expression * 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
     2125template< typename pass_type >
     2126void 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
     2139template< typename pass_type >
     2140Expression * 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//--------------------------------------------------------------------------
    20762155// VoidType
    20772156template< typename pass_type >
  • TabularUnified src/Common/SemanticError.cc

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

    r0182bfa r28f3a19  
    192192                void postvisit(   StructDecl * decl );
    193193
    194                 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
     194                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
    195195                void validate( DeclarationWithType * );
    196196                void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     
    431431        void MutexKeyword::postvisit(FunctionDecl* decl) {
    432432
    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 
     433                bool first = false;
     434                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
    438435                bool isDtor = CodeGen::isDestructor( decl->name );
    439436
     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
    440467                if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
    441468
     469                // Make sure all the mutex arguments are monitors
    442470                for(auto arg : mutexArgs) {
    443471                        validate( arg );
    444472                }
    445473
     474                // Check if we need to instrument the body
    446475                CompoundStmt* body = decl->get_statements();
    447476                if( ! body ) return;
    448477
     478                // Do we have the required headers
    449479                if( !monitor_decl || !guard_decl || !dtor_guard_decl )
    450                         SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
    451 
     480                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>\n" );
     481
     482                // Instrument the body
    452483                if( isDtor ) {
    453484                        addDtorStatments( decl, body, mutexArgs );
     
    474505        }
    475506
    476         std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
     507        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) {
    477508                std::list<DeclarationWithType*> mutexArgs;
    478509
     510                bool once = true;
    479511                for( auto arg : decl->get_functionType()->get_parameters()) {
    480512                        //Find mutex arguments
    481513                        Type* ty = arg->get_type();
    482514                        if( ! ty->get_mutex() ) continue;
     515
     516                        if(once) {first = true;}
     517                        once = false;
    483518
    484519                        //Append it to the list
  • TabularUnified src/ControlStruct/ForExprMutator.cc

    r0182bfa r28f3a19  
    4545                return hoist( forStmt, forStmt->initialization );
    4646        }
     47        Statement *ForExprMutator::postmutate( WhileStmt *whileStmt ) {
     48                return hoist( whileStmt, whileStmt->initialization );
     49        }
    4750} // namespace ControlStruct
    4851
  • TabularUnified src/ControlStruct/ForExprMutator.h

    r0182bfa r28f3a19  
    1818class IfStmt;
    1919class ForStmt;
     20class WhileStmt;
    2021class Statement;
    2122
     
    2526                Statement *postmutate( IfStmt * );
    2627                Statement *postmutate( ForStmt * );
     28                Statement *postmutate( WhileStmt * );
    2729        };
    2830} // namespace ControlStruct
  • TabularUnified src/ControlStruct/Mutate.cc

    r0182bfa r28f3a19  
    2727#include "SynTree/Visitor.h"       // for acceptAll
    2828
    29 using namespace std;
     29namespace ControlStruct {
     30        void fixLabels( std::list< Declaration * > & translationUnit ) {
     31                PassVisitor<LabelFixer> lfix;
     32                acceptAll( translationUnit, lfix );
     33        }
    3034
    31 namespace ControlStruct {
    32         void mutate( std::list< Declaration * > translationUnit ) {
    33                 // hoist initialization out of for statements
     35        void hoistControlDecls( std::list< Declaration * > & translationUnit ) {
    3436                PassVisitor<ForExprMutator> formut;
    35 
    36                 // normalizes label definitions and generates multi-level exit labels
    37                 PassVisitor<LabelFixer> lfix;
    38 
    3937                mutateAll( translationUnit, formut );
    40                 acceptAll( translationUnit, lfix );
    4138        }
    4239} // namespace CodeGen
  • TabularUnified src/ControlStruct/Mutate.h

    r0182bfa r28f3a19  
    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
    2223namespace ControlStruct {
    23         /// Desugars Cforall control structures
    24         void mutate( std::list< Declaration* > translationUnit );
     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 );
    2529} // namespace ControlStruct
    2630
  • TabularUnified src/GenPoly/Lvalue.cc

    r0182bfa r28f3a19  
    145145
    146146        namespace {
    147                 // true for intrinsic function calls that return a reference
     147                // true for intrinsic function calls that return an lvalue in C
    148148                bool isIntrinsicReference( Expression * expr ) {
     149                        // known intrinsic-reference prelude functions
     150                        static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    149151                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    150152                                std::string fname = InitTweak::getFunctionName( untyped );
    151                                 // known intrinsic-reference prelude functions
    152                                 return fname == "*?" || fname == "?[?]";
     153                                return lvalueFunctions.count(fname);
    153154                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    154155                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    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 );
     156                                        return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
    159157                                }
    160158                        }
     
    210208                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    211209
    212                                                 if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     210                                                if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    213211                                                        // needed for definition of prelude functions, etc.
    214212                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    226224                                                        arg = new AddressExpr( arg );
    227225                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    228                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     226                                                } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    229227                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    230228                                                        PRINT(
  • TabularUnified src/Parser/DeclarationNode.cc

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 22 08:39:29 2018
    13 // Update Count     : 1074
     12// Last Modified On : Thu Jun  7 12:08:55 2018
     13// Update Count     : 1079
    1414//
    1515
     
    173173}
    174174
    175 DeclarationNode * DeclarationNode::newFunction( string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
     175DeclarationNode * DeclarationNode::newFunction( const 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( string * name ) {
     246DeclarationNode * DeclarationNode::newFromTypedef( const string * name ) {
    247247        DeclarationNode * newnode = new DeclarationNode;
    248248        newnode->type = new TypeData( TypeData::SymbolicInst );
     
    267267} // DeclarationNode::newAggregate
    268268
    269 DeclarationNode * DeclarationNode::newEnum( string * name, DeclarationNode * constants, bool body ) {
     269DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body ) {
    270270        assert( name );
    271271        DeclarationNode * newnode = new DeclarationNode;
     
    277277} // DeclarationNode::newEnum
    278278
    279 DeclarationNode * DeclarationNode::newEnumConstant( string * name, ExpressionNode * constant ) {
     279DeclarationNode * DeclarationNode::newEnumConstant( const string * name, ExpressionNode * constant ) {
    280280        DeclarationNode * newnode = new DeclarationNode;
    281281        newnode->name = name;
     
    284284} // DeclarationNode::newEnumConstant
    285285
    286 DeclarationNode * DeclarationNode::newName( string * name ) {
     286DeclarationNode * DeclarationNode::newName( const string * name ) {
    287287        DeclarationNode * newnode = new DeclarationNode;
    288288        newnode->name = name;
     
    290290} // DeclarationNode::newName
    291291
    292 DeclarationNode * DeclarationNode::newFromTypeGen( string * name, ExpressionNode * params ) {
     292DeclarationNode * DeclarationNode::newFromTypeGen( const 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, string * name ) {
     301DeclarationNode * DeclarationNode::newTypeParam( TypeClass tc, const string * name ) {
    302302        DeclarationNode * newnode = new DeclarationNode;
    303303        newnode->type = nullptr;
     
    330330} // DeclarationNode::newTraitUse
    331331
    332 DeclarationNode * DeclarationNode::newTypeDecl( string * name, DeclarationNode * typeParams ) {
     332DeclarationNode * DeclarationNode::newTypeDecl( const string * name, DeclarationNode * typeParams ) {
    333333        DeclarationNode * newnode = new DeclarationNode;
    334334        newnode->name = name;
     
    405405} // DeclarationNode::newBuiltinType
    406406
    407 DeclarationNode * DeclarationNode::newAttr( string * name, ExpressionNode * expr ) {
     407DeclarationNode * DeclarationNode::newAttr( const string * name, ExpressionNode * expr ) {
    408408        DeclarationNode * newnode = new DeclarationNode;
    409409        newnode->type = nullptr;
     
    414414}
    415415
    416 DeclarationNode * DeclarationNode::newAttr( string * name, DeclarationNode * type ) {
     416DeclarationNode * DeclarationNode::newAttr( const string * name, DeclarationNode * type ) {
    417417        DeclarationNode * newnode = new DeclarationNode;
    418418        newnode->type = nullptr;
     
    423423}
    424424
    425 DeclarationNode * DeclarationNode::newAttribute( string * name, ExpressionNode * expr ) {
     425DeclarationNode * DeclarationNode::newAttribute( const 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; // make polymorphic type
    547                                         // change implicit typedef from TYPEDEFname to TYPEGENname
    548                                         typedefTable.changeKind( *type->aggregate.name, TYPEGENname );
     546                                        type->aggregate.params = q->type->forall; // set forall qualifier
    549547                                } // if
    550548                        } else {                                                                        // not polymorphic
     
    10651063                        SemanticError( this, "invalid function specifier for " );
    10661064                } // if
    1067                 return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
     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;
    10681072        } // if
    10691073
  • TabularUnified src/Parser/ExpressionNode.cc

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

    r0182bfa r28f3a19  
    2727
    2828InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
    29                 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ) {
     29                : expr( _expr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
    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 ) {
     38                : expr( nullptr ), aggregate( aggrp ), designator( des ), kids( nullptr ), maybeConstructed( true ), isDelete( false ) {
    3939        if ( init )
    4040                set_last( init );
     
    4646                set_next( nullptr );
    4747} // InitializerNode::InitializerNode
     48
     49InitializerNode::InitializerNode( bool isDelete ) : expr( nullptr ), aggregate( false ), designator( nullptr ), kids( nullptr ), maybeConstructed( false ), isDelete( isDelete ) {}
    4850
    4951InitializerNode::~InitializerNode() {
     
    8486
    8587Initializer * InitializerNode::build() const {
     88        assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
    8689        if ( aggregate ) {
    8790                // steal designators from children
  • TabularUnified src/Parser/ParseNode.h

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 30 09:19:17 2018
    13 // Update Count     : 831
     12// Last Modified On : Wed Jun  6 16:17:18 2018
     13// Update Count     : 843
    1414//
    1515
     
    7777
    7878        ParseNode * next = nullptr;
    79         std::string * name = nullptr;
     79        const 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 );
    8990        ~InitializerNode();
    9091        virtual InitializerNode * clone() const { assert( false ); return nullptr; }
     
    9798        InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
    9899        bool get_maybeConstructed() const { return maybeConstructed; }
     100
     101        bool get_isDelete() const { return isDelete; }
    99102
    100103        InitializerNode * next_init() const { return kids; }
     
    110113        InitializerNode * kids;
    111114        bool maybeConstructed;
     115        bool isDelete;
    112116}; // InitializerNode
    113117
     
    167171};
    168172
    169 Expression * build_constantInteger( std::string &str );
    170 Expression * build_constantFloat( std::string &str );
    171 Expression * build_constantChar( std::string &str );
    172 Expression * build_constantStr( std::string &str );
     173Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
     174Expression * build_constantFloat( std::string & str );
     175Expression * build_constantChar( std::string & str );
     176Expression * build_constantStr( std::string & str );
    173177Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
    174178Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
     
    226230        static DeclarationNode * newBuiltinType( BuiltinType );
    227231        static DeclarationNode * newForall( DeclarationNode * );
    228         static DeclarationNode * newFromTypedef( std::string * );
    229         static DeclarationNode * newFunction( std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
     232        static DeclarationNode * newFromTypedef( const std::string * );
     233        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    230234        static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    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 * );
     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 * );
    236240        static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
    237241        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    238         static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
     242        static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );
    239243        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    240244        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
     
    243247        static DeclarationNode * newTuple( DeclarationNode * members );
    244248        static DeclarationNode * newTypeof( ExpressionNode * expr );
    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
     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
    248252        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
    249253        static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
     
    399403};
    400404
     405Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init );
    401406Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
    402407Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
    403408Statement * build_case( ExpressionNode * ctl );
    404409Statement * build_default();
    405 Statement * build_while( ExpressionNode * ctl, StatementNode * stmt, bool kind = false );
     410Statement * build_while( IfCtl * ctl, StatementNode * stmt );
     411Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt );
    406412Statement * build_for( ForCtl * forctl, StatementNode * stmt );
    407413Statement * build_branch( BranchStmt::Type kind );
  • TabularUnified src/Parser/StatementNode.cc

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 30 09:21:16 2018
    13 // Update Count     : 354
     12// Last Modified On : Tue Jun  5 08:58:34 2018
     13// Update Count     : 362
    1414//
    1515
     
    6969        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
    7070        return this;
    71 }
     71} // StatementNode::append_last_case
    7272
    7373Statement * build_expr( ExpressionNode * ctl ) {
    7474        Expression * e = maybeMoveBuild< Expression >( ctl );
    7575
    76         if ( e )
    77                 return new ExprStmt( e );
    78         else
    79                 return new NullStmt();
    80 }
    81 
    82 Statement * 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;
     76        if ( e ) return new ExprStmt( e );
     77        else return new NullStmt();
     78} // build_expr
     79
     80Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init ) {
    9781        if ( ctl->init != 0 ) {
    9882                buildMoveList( ctl->init, init );
     
    10286        if ( ctl->condition ) {
    10387                // compare the provided condition against 0
    104                 cond =  notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
     88                cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
    10589        } else {
    10690                for ( Statement * stmt : init ) {
     
    11397        }
    11498        delete ctl;
     99        return cond;
     100} // build_if_control
     101
     102Statement * 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 );
    115118        return new IfStmt( cond, thenb, elseb, init );
    116 }
     119} // build_if
    117120
    118121Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
     
    130133        // branches.size() == 0 for switch (...) {}, i.e., no declaration or statements
    131134        return new SwitchStmt( maybeMoveBuild< Expression >(ctl), branches );
    132 }
     135} // build_switch
     136
    133137Statement * build_case( ExpressionNode * ctl ) {
    134138        std::list< Statement * > branches;
    135139        return new CaseStmt( maybeMoveBuild< Expression >(ctl), branches );
    136 }
     140} // build_case
     141
    137142Statement * build_default() {
    138143        std::list< Statement * > branches;
    139144        return new CaseStmt( nullptr, branches, true );
    140 }
    141 
    142 Statement * build_while( ExpressionNode * ctl, StatementNode * stmt, bool kind ) {
    143         std::list< Statement * > branches;
    144         buildMoveList< Statement, StatementNode >( stmt, branches );
    145         assert( branches.size() == 1 );
    146         return new WhileStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind );
    147 }
     145} // build_default
     146
     147Statement * build_while( IfCtl * ctl, StatementNode * stmt ) {
     148        std::list< Statement * > branches;
     149        buildMoveList< Statement, StatementNode >( stmt, branches );
     150        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
     157Statement * 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
    148165
    149166Statement * build_for( ForCtl * forctl, StatementNode * stmt ) {
     
    167184        delete forctl;
    168185        return new ForStmt( init, cond, incr, branches.front() );
    169 }
     186} // build_for
    170187
    171188Statement * build_branch( BranchStmt::Type kind ) {
    172189        Statement * ret = new BranchStmt( "", kind );
    173190        return ret;
    174 }
     191} // build_branch
     192
    175193Statement * build_branch( std::string * identifier, BranchStmt::Type kind ) {
    176194        Statement * ret = new BranchStmt( * identifier, kind );
    177195        delete identifier;                                                                      // allocated by lexer
    178196        return ret;
    179 }
     197} // build_branch
     198
    180199Statement * build_computedgoto( ExpressionNode * ctl ) {
    181200        return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
    182 }
     201} // build_computedgoto
    183202
    184203Statement * build_return( ExpressionNode * ctl ) {
     
    186205        buildMoveList( ctl, exps );
    187206        return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
    188 }
     207} // build_return
    189208
    190209Statement * build_throw( ExpressionNode * ctl ) {
     
    193212        assertf( exps.size() < 2, "This means we are leaking memory");
    194213        return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
    195 }
     214} // build_throw
    196215
    197216Statement * build_resume( ExpressionNode * ctl ) {
     
    200219        assertf( exps.size() < 2, "This means we are leaking memory");
    201220        return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
    202 }
     221} // build_resume
    203222
    204223Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     
    206225        (void)target;
    207226        assertf( false, "resume at (non-local throw) is not yet supported," );
    208 }
     227} // build_resume_at
    209228
    210229Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt ) {
     
    214233        FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) );
    215234        return new TryStmt( tryBlock, branches, finallyBlock );
    216 }
     235} // build_try
     236
    217237Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    218238        std::list< Statement * > branches;
     
    220240        assert( branches.size() == 1 );
    221241        return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
    222 }
     242} // build_catch
     243
    223244Statement * build_finally( StatementNode * stmt ) {
    224245        std::list< Statement * > branches;
     
    226247        assert( branches.size() == 1 );
    227248        return new FinallyStmt( dynamic_cast< CompoundStmt * >( branches.front() ) );
    228 }
     249} // build_finally
    229250
    230251WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
     
    247268
    248269        return node;
    249 }
     270} // build_waitfor
    250271
    251272WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
     
    266287
    267288        return node;
    268 }
     289} // build_waitfor
    269290
    270291WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
     
    275296                node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    276297                node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    277         }
    278         else {
     298        } else {
    279299                node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
    280300                node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    281         }
     301        } // if
    282302
    283303        return node;
    284 }
     304} // build_waitfor_timeout
    285305
    286306WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_stmt, ExpressionNode * else_when ) {
     
    295315
    296316        return node;
    297 }
     317} // build_waitfor_timeout
    298318
    299319WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     
    302322        Statement * s = maybeMoveBuild<Statement>( stmt );
    303323        return new WithStmt( e, s );
    304 }
     324} // build_with
    305325
    306326Statement * build_compound( StatementNode * first ) {
     
    308328        buildMoveList( first, cs->get_kids() );
    309329        return cs;
    310 }
     330} // build_compound
    311331
    312332Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     
    318338        buildMoveList( clobber, clob );
    319339        return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    320 }
     340} // build_asm
    321341
    322342Statement * build_directive( string * directive ) {
    323343        return new DirectiveStmt( *directive );
    324 }
     344} // build_directive
    325345
    326346// Local Variables: //
  • TabularUnified src/Parser/TypeData.cc

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 26 13:46:07 2018
    13 // Update Count     : 603
     12// Last Modified On : Wed Jun  6 17:40:33 2018
     13// Update Count     : 604
    1414//
    1515
     
    6565          case Aggregate:
    6666                // aggregate = new Aggregate_t;
     67                aggregate.kind = DeclarationNode::NoAggregate;
    6768                aggregate.name = nullptr;
    6869                aggregate.params = nullptr;
     
    7071                aggregate.fields = nullptr;
    7172                aggregate.body = false;
     73                aggregate.tagged = false;
     74                aggregate.parent = nullptr;
    7275                break;
    7376          case AggregateInst:
     
    198201                break;
    199202          case Aggregate:
     203                newtype->aggregate.kind = aggregate.kind;
    200204                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
    201205                newtype->aggregate.params = maybeClone( aggregate.params );
    202206                newtype->aggregate.actuals = maybeClone( aggregate.actuals );
    203207                newtype->aggregate.fields = maybeClone( aggregate.fields );
    204                 newtype->aggregate.kind = aggregate.kind;
    205208                newtype->aggregate.body = aggregate.body;
    206209                newtype->aggregate.tagged = aggregate.tagged;
     
    575578
    576579          case DeclarationNode::Int128:
    577                 ret = td->signedness == 1 ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
     580                ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
    578581                if ( td->length != DeclarationNode::NoLength ) {
    579582                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     
    599602                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    600603                } // if
    601                 if ( td->basictype == DeclarationNode::Float && td->length == DeclarationNode::Long ) {
     604                if ( td->basictype != DeclarationNode::Double && td->length == DeclarationNode::Long ) {
    602605                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    603606                } // if
     
    605608                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
    606609                } // 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                }
    607619
    608620                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
  • TabularUnified src/Parser/TypedefTable.cc

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 15:20:13 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 22 08:40:01 2018
    13 // Update Count     : 121
     12// Last Modified On : Fri Jun 22 06:14:39 2018
     13// Update Count     : 206
    1414//
    1515
     
    1717#include "TypedefTable.h"
    1818#include <cassert>                                                                              // for assert
     19#include <iostream>
    1920
    2021#if 0
    21 #include <iostream>
    22 #define debugPrint( x ) cerr << x
     22#define debugPrint( code ) code
    2323#else
    24 #define debugPrint( x )
     24#define debugPrint( code )
    2525#endif
    2626
    2727using namespace std;                                                                    // string, iostream
    2828
     29debugPrint(
     30static 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
    2942TypedefTable::~TypedefTable() {
    3043        if ( ! SemanticErrorThrow && kindTable.currentScope() != 0 ) {
    31                 // std::cerr << "scope failure " << kindTable.currentScope() << endl;
     44                cerr << "Error: cfa-cpp internal error, scope failure " << kindTable.currentScope() << endl;
     45                abort();
    3246        } // if
    3347} // TypedefTable::~TypedefTable
     
    4458} // TypedefTable::isKind
    4559
    46 void 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 
    5160// SKULLDUGGERY: Generate a typedef for the aggregate name so the aggregate does not have to be qualified by
    5261// "struct". Only generate the typedef, if the name is not in use. The typedef is implicitly (silently) removed if the
    5362// name is explicitly used.
    54 void TypedefTable::makeTypedef( const string & name ) {
     63void 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//        }
    5571        if ( ! typedefTable.exists( name ) ) {
    56                 typedefTable.addToEnclosingScope( name, TYPEDEFname );
     72                typedefTable.addToEnclosingScope( name, kind, "MTD" );
    5773        } // if
    5874} // TypedefTable::makeTypedef
    5975
    60 void 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 );
     76void 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
     84void 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 );
    6488        auto ret = kindTable.insertAt( scope, identifier, kind );
    6589        if ( ! ret.second ) ret.first->second = kind;           // exists => update
     
    6892void TypedefTable::enterScope() {
    6993        kindTable.beginScope();
    70         debugPrint( "Entering scope " << kindTable.currentScope() << endl );
     94        debugPrint( cerr << "Entering scope " << kindTable.currentScope() << endl; print() );
    7195} // TypedefTable::enterScope
    7296
    7397void TypedefTable::leaveScope() {
    74         debugPrint( "Leaving scope " << kindTable.currentScope() << endl );
     98        debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl; print() );
    7599        kindTable.endScope();
    76100} // TypedefTable::leaveScope
    77101
    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 // }
     102void 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
    88118
    89119// Local Variables: //
  • TabularUnified src/Parser/TypedefTable.h

    r0182bfa r28f3a19  
    1010// Created On       : Sat May 16 15:24:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 22 08:39:29 2018
    13 // Update Count     : 77
     12// Last Modified On : Fri Jun 22 05:29:58 2018
     13// Update Count     : 86
    1414//
    1515
     
    2525        typedef ScopedMap< std::string, int > KindTable;
    2626        KindTable kindTable;   
     27        unsigned int level = 0;
    2728  public:
    2829        ~TypedefTable();
     
    3031        bool exists( const std::string & identifier );
    3132        int isKind( const std::string & identifier ) const;
    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 );
     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 * );
    3536
    3637        void enterScope();
    3738        void leaveScope();
     39
     40        void up() { level += 1; }
     41        void down() { level -= 1; }
     42
     43        void print( void ) const;
    3844}; // TypedefTable
    3945
  • TabularUnified src/Parser/lex.ll

    r0182bfa r28f3a19  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu May  3 13:42:40 2018
    13  * Update Count     : 676
     12 * Last Modified On : Wed Jun 20 09:08:28 2018
     13 * Update Count     : 682
    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 : "";
    2735unsigned 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
    2936
    3037#include <string>
     
    4956#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL( x ) // numeric constant
    5057#define KEYWORD_RETURN(x)       RETURN_CHAR( x )                        // keyword
    51 #define QKEYWORD_RETURN(x)      typedefTable.isKind( yytext ); RETURN_VAL(x); // quasi-keyword
     58#define QKEYWORD_RETURN(x)      RETURN_VAL(x);                          // quasi-keyword
    5259#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    5360#define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
     
    232239finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    233240float                   { 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
    234245__float80               { KEYWORD_RETURN(FLOAT80); }                    // GCC
    235246float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
     247_Float128               { KEYWORD_RETURN(FLOAT128); }                   // GCC
     248_Float128x              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    236249__float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    237250float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
     
    446459
    447460%%
     461
    448462// ----end of lexer----
    449463
    450464void yyerror( const char * errmsg ) {
     465        SemanticErrorThrow = true;
    451466        cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    452467                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
  • TabularUnified src/Parser/parser.yy

    r0182bfa r28f3a19  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 24 18:11:59 2018
    13 // Update Count     : 3369
     12// Last Modified On : Fri Jun 22 13:59:11 2018
     13// Update Count     : 3586
    1414//
    1515
     
    136136} // build_postfix_name
    137137
    138 bool forall = false, xxx = false;                                               // aggregate have one or more forall qualifiers ?
     138bool forall = false, xxx = false, yyy = 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;
    177178}
    178179
     
    259260%type<flag> asm_volatile_opt
    260261%type<en> handler_predicate_opt
     262%type<genexpr> generic_association generic_assoc_list
    261263
    262264// statements
    263265%type<sn> statement                                             labeled_statement                       compound_statement
    264266%type<sn> statement_decl                                statement_decl_list                     statement_list_nodecl
    265 %type<sn> selection_statement
     267%type<sn> selection_statement                   if_statement
    266268%type<sn> switch_clause_list_opt                switch_clause_list
    267269%type<en> case_value
     
    302304%type<en> enumerator_value_opt
    303305
    304 %type<decl> exception_declaration external_definition external_definition_list external_definition_list_opt
     306%type<decl> external_definition external_definition_list external_definition_list_opt
     307
     308%type<decl> exception_declaration
    305309
    306310%type<decl> field_declaration field_declaration_list_opt field_declarator_opt field_declaring_list
     
    324328%type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr
    325329
    326 %type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_type_list_opt
     330%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt
    327331
    328332%type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier
     
    330334%type<decl> c_declaration static_assert
    331335%type<decl> KR_function_declarator KR_function_no_ptr KR_function_ptr KR_function_array
    332 %type<decl> KR_declaration_list KR_declaration_list_opt
     336%type<decl> KR_parameter_list KR_parameter_list_opt
    333337
    334338%type<decl> parameter_declaration parameter_list parameter_type_list_opt
     
    402406//************************* Namespace Management ********************************
    403407
    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.
     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
    426434
    427435push:
     
    497505                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    498506        | type_name '.' no_attr_identifier                                      // CFA, nested type
    499                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     507                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     508                { $$ = nullptr; }
    500509        | type_name '.' '[' field_list ']'                                      // CFA, nested type / tuple field selector
    501                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     510                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     511                { $$ = nullptr; }
    502512        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    503                 { SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; }
     513                {
     514                        // add the missing control expression to the GenericExpr and return it
     515                        $5->control = maybeMoveBuild<Expression>( $3 );
     516                        $$ = new ExpressionNode( $5 );
     517                }
    504518        ;
    505519
    506520generic_assoc_list:                                                                             // C11
    507         | generic_association
     521        generic_association
    508522        | 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                }
    509529        ;
    510530
    511531generic_association:                                                                    // C11
    512532        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                }
    513537        | DEFAULT ':' assignment_expression
     538                { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>($3) } } ); }
    514539        ;
    515540
     
    623648                // semantics checks, e.g., ++3, 3--, *3, &&3
    624649        | constant
    625                 { $$ = $1; }
    626650        | string_literal
    627651                { $$ = new ExpressionNode( $1 ); }
     
    835859//      '[' ']'
    836860//              { $$ = new ExpressionNode( build_tuple() ); }
    837 //      '[' push assignment_expression pop ']'
     861//      | '[' push assignment_expression pop ']'
    838862//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    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 ) ) ); }
     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 ) ) ); }
    843867        ;
    844868
     
    892916        '{' '}'
    893917                { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
    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
     918        | '{' push
    898919          local_label_declaration_opt                                           // GCC, local labels
    899920          statement_decl_list                                                           // C99, intermix declarations and statements
    900921          pop '}'
    901                 { $$ = new StatementNode( build_compound( $5 ) ); }
     922                { $$ = new StatementNode( build_compound( $4 ) ); }
    902923        ;
    903924
    904925statement_decl_list:                                                                    // C99
    905926        statement_decl
    906         | statement_decl_list push statement_decl
    907                 { if ( $1 != 0 ) { $1->set_last( $3 ); $$ = $1; } }
     927        | statement_decl_list statement_decl
     928                { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
    908929        ;
    909930
     
    923944                        $$ = new StatementNode( $2 );
    924945                }
    925         | statement pop
     946        | statement
    926947        ;
    927948
     
    938959
    939960selection_statement:
    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 ) ); }
     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; }
    945965        | SWITCH '(' comma_expression ')' case_clause
    946966                { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
    947         | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
     967        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    948968                {
    949969                        StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
     
    957977        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    958978                { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
    959         | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
     979        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    960980                {
    961981                        StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
     
    964984        ;
    965985
     986if_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
    966994if_control_expression:
    967         comma_expression pop
     995        comma_expression
    968996                { $$ = new IfCtl( nullptr, $1 ); }
    969         | c_declaration pop                                                                     // no semi-colon
     997        | c_declaration                                                                         // no semi-colon
    970998                { $$ = new IfCtl( $1, nullptr ); }
    971         | cfa_declaration pop                                                           // no semi-colon
     999        | cfa_declaration                                                                       // no semi-colon
    9721000                { $$ = new IfCtl( $1, nullptr ); }
    9731001        | declaration comma_expression                                          // semi-colon separated
     
    10261054
    10271055iteration_statement:
    1028         WHILE '(' comma_expression ')' statement
    1029                 { $$ = new StatementNode( build_while( $3, $5 ) ); }
     1056        WHILE '(' push if_control_expression ')' statement pop
     1057                { $$ = new StatementNode( build_while( $4, $6 ) ); }
    10301058        | DO statement WHILE '(' comma_expression ')' ';'
    1031                 { $$ = new StatementNode( build_while( $5, $2, true ) ); }
    1032         | FOR '(' push for_control_expression ')' statement
     1059                { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
     1060        | FOR '(' push for_control_expression ')' statement pop
    10331061                { $$ = new StatementNode( build_for( $4, $6 ) ); }
    10341062        ;
    10351063
    10361064for_control_expression:
    1037         comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
    1038                 { $$ = new ForCtl( $1, $4, $6 ); }
     1065        comma_expression_opt ';' comma_expression_opt ';' comma_expression_opt
     1066                { $$ = new ForCtl( $1, $3, $5 ); }
    10391067        | declaration comma_expression_opt ';' comma_expression_opt // C99
    10401068                { $$ = new ForCtl( $1, $2, $4 ); }
     
    11581186
    11591187handler_clause:
    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 ) ) ); }
     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 ) ) ); }
    11641192        ;
    11651193
     
    12651293
    12661294declaration_list_opt:                                                                   // used at beginning of switch statement
    1267         pop     // empty
     1295        // empty
    12681296                { $$ = nullptr; }
    12691297        | declaration_list
     
    12721300declaration_list:
    12731301        declaration
    1274         | declaration_list push declaration
    1275                 { $$ = $1->appendList( $3 ); }
    1276         ;
    1277 
    1278 KR_declaration_list_opt:                                                                // used to declare parameter types in K&R style functions
     1302        | declaration_list declaration
     1303                { $$ = $1->appendList( $2 ); }
     1304        ;
     1305
     1306KR_parameter_list_opt:                                                                  // used to declare parameter types in K&R style functions
    12791307        // empty
    12801308                { $$ = nullptr; }
    1281         | KR_declaration_list
    1282         ;
    1283 
    1284 KR_declaration_list:
     1309        | KR_parameter_list
     1310        ;
     1311
     1312KR_parameter_list:
    12851313        push c_declaration pop ';'
    12861314                { $$ = $2; }
    1287         | KR_declaration_list push c_declaration pop ';'
     1315        | KR_parameter_list push c_declaration pop ';'
    12881316                { $$ = $1->appendList( $3 ); }
    12891317        ;
     
    13051333
    13061334declaration:                                                                                    // old & new style declarations
    1307         c_declaration pop ';'
    1308         | cfa_declaration pop ';'                                                       // CFA
    1309         | static_assert
     1335        c_declaration ';'
     1336        | cfa_declaration ';'                                                           // CFA
     1337        | static_assert                                                                         // C11
    13101338        ;
    13111339
     
    13131341        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    13141342                { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
     1343        | STATICASSERT '(' constant_expression ')' ';'          // CFA
     1344                { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
    13151345
    13161346// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    13571387cfa_function_declaration:                                                               // CFA
    13581388        cfa_function_specifier
    1359                 { $$ = $1; }
    13601389        | type_qualifier_list cfa_function_specifier
    13611390                { $$ = $2->addQualifiers( $1 ); }
     
    13641393        | declaration_qualifier_list type_qualifier_list cfa_function_specifier
    13651394                { $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); }
    1366         | cfa_function_declaration ',' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
     1395        | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
    13671396                {
    13681397                        // Append the return type at the start (left-hand-side) to each identifier in the list.
    13691398                        DeclarationNode * ret = new DeclarationNode;
    13701399                        ret->type = maybeClone( $1->type->base );
    1371                         $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $5, nullptr ) );
     1400                        $$ = $1->appendList( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
    13721401                }
    13731402        ;
    13741403
    13751404cfa_function_specifier:                                                                 // CFA
    1376 //      '[' ']' identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')' // S/R conflict
     1405//      '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
    13771406//              {
    13781407//                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );
    13791408//              }
    1380 //      '[' ']' identifier '(' push cfa_parameter_type_list_opt pop ')'
     1409//      '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
    13811410//              {
    13821411//                      typedefTable.setNextIdentifier( *$5 );
    13831412//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    13841413//              }
    1385 //      | '[' ']' TYPEDEFname '(' push cfa_parameter_type_list_opt pop ')'
     1414//      | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
    13861415//              {
    13871416//                      typedefTable.setNextIdentifier( *$5 );
     
    13911420                // identifier_or_type_name must be broken apart because of the sequence:
    13921421                //
    1393                 //   '[' ']' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
     1422                //   '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
    13941423                //   '[' ']' type_specifier
    13951424                //
    13961425                // type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be
    13971426                // flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name.
    1398         cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
     1427        cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
    13991428                // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
    14001429                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); }
    1401         | cfa_function_return identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
     1430        | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
    14021431                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 ); }
    14031432        ;
     
    14141443        TYPEDEF cfa_variable_specifier
    14151444                {
    1416                         typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname );
     1445                        typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "1" );
    14171446                        $$ = $2->addTypedef();
    14181447                }
    14191448        | TYPEDEF cfa_function_specifier
    14201449                {
    1421                         typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname );
     1450                        typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "2" );
    14221451                        $$ = $2->addTypedef();
    14231452                }
    14241453        | cfa_typedef_declaration pop ',' push no_attr_identifier
    14251454                {
    1426                         typedefTable.addToEnclosingScope( *$5, TYPEDEFname );
     1455                        typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "3" );
    14271456                        $$ = $1->appendList( $1->cloneType( $5 ) );
    14281457                }
     
    14351464        TYPEDEF type_specifier declarator
    14361465                {
    1437                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname );
     1466                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
    14381467                        $$ = $3->addType( $2 )->addTypedef();
    14391468                }
    14401469        | typedef_declaration pop ',' push declarator
    14411470                {
    1442                         typedefTable.addToEnclosingScope( *$5->name, TYPEDEFname );
     1471                        typedefTable.addToEnclosingScope( *$5->name, TYPEDEFname, "5" );
    14431472                        $$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
    14441473                }
    14451474        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
    14461475                {
    1447                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname );
     1476                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
    14481477                        $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
    14491478                }
    14501479        | type_specifier TYPEDEF declarator
    14511480                {
    1452                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname );
     1481                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
    14531482                        $$ = $3->addType( $1 )->addTypedef();
    14541483                }
    14551484        | type_specifier TYPEDEF type_qualifier_list declarator
    14561485                {
    1457                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname );
     1486                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
    14581487                        $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
    14591488                }
     
    15821611
    15831612forall:
    1584         FORALL '(' push type_parameter_list pop ')'                                     // CFA
    1585                 { $$ = DeclarationNode::newForall( $4 ); }
     1613        FORALL '(' type_parameter_list ')'                                      // CFA
     1614                { $$ = DeclarationNode::newForall( $3 ); }
    15861615        ;
    15871616
     
    17651794                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    17661795        | '.' TYPEDEFname
    1767                 { $$ = DeclarationNode::newFromTypedef( $2 ); } // FIX ME
     1796                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17681797        | type_name '.' TYPEDEFname
    1769                 { $$ = DeclarationNode::newFromTypedef( $3 ); } // FIX ME
     1798                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17701799        | typegen_name
    17711800        | '.' typegen_name
    1772                 { $$ = $2; }                                                                    // FIX ME
     1801                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17731802        | type_name '.' typegen_name
    1774                 { $$ = $3; }                                                                    // FIX ME
     1803                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    17751804        ;
    17761805
     
    17941823        ;
    17951824
     1825fred:
     1826        // empty
     1827                { yyy = false; }
     1828        ;
     1829
    17961830aggregate_type:                                                                                 // struct, union
    17971831        aggregate_key attribute_list_opt '{' field_declaration_list_opt '}'
    17981832                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), nullptr, $4, true )->addQualifiers( $2 ); }
    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
     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
    18031837                        forall = false;                                                         // reset
    18041838                }
    18051839          '{' field_declaration_list_opt '}'
    1806                 { $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $6, true )->addQualifiers( $2 ); }
     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 ); }
    18071849        | aggregate_key attribute_list_opt '(' type_list ')' '{' field_declaration_list_opt '}' // CFA
    18081850                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), $4, $7, false )->addQualifiers( $2 ); }
     
    18111853
    18121854aggregate_type_nobody:                                                                  // struct, union - {...}
    1813         aggregate_key attribute_list_opt no_attr_identifier
    1814                 {
    1815                         typedefTable.makeTypedef( *$3 );
    1816                         if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
     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
    18171859                        forall = false;                                                         // reset
    18181860                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    18191861                }
    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
     1862        | aggregate_key attribute_list_opt type_name fred
    18261863                {
    18271864                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
     
    18371874aggregate_key:
    18381875        STRUCT
    1839                 { $$ = DeclarationNode::Struct; }
     1876                { yyy = true; $$ = DeclarationNode::Struct; }
    18401877        | UNION
    1841                 { $$ = DeclarationNode::Union; }
     1878                { yyy = true; $$ = DeclarationNode::Union; }
    18421879        | EXCEPTION
    1843                 { $$ = DeclarationNode::Exception; }
     1880                { yyy = true; $$ = DeclarationNode::Exception; }
    18441881        | COROUTINE
    1845                 { $$ = DeclarationNode::Coroutine; }
     1882                { yyy = true; $$ = DeclarationNode::Coroutine; }
    18461883        | MONITOR
    1847                 { $$ = DeclarationNode::Monitor; }
     1884                { yyy = true; $$ = DeclarationNode::Monitor; }
    18481885        | THREAD
    1849                 { $$ = DeclarationNode::Thread; }
     1886                { yyy = true; $$ = DeclarationNode::Thread; }
    18501887        ;
    18511888
     
    18581895
    18591896field_declaration:
    1860         cfa_field_declaring_list ';'                                            // CFA, new style field declaration
     1897        type_specifier field_declaring_list ';'
     1898                { $$ = distAttr( $1, $2 ); }
     1899        | 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
    18611904        | 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 ); }
    1869         | EXTENSION type_specifier field_declaring_list ';'     // GCC
    1870                 {
    1871                         distExt( $3 );                                                          // mark all fields in list
    1872                         $$ = distAttr( $2, $3 );
    1873                 }
    1874         | static_assert
     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
    18751909        ;
    18761910
     
    19111945                { $$ = nullptr; }
    19121946        | bit_subrange_size
    1913                 { $$ = $1; }
    19141947        ;
    19151948
     
    19221955        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    19231956                { $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
    1924         | ENUM attribute_list_opt no_attr_identifier_or_type_name
     1957        | ENUM attribute_list_opt no_attr_identifier
    19251958                { typedefTable.makeTypedef( *$3 ); }
    19261959          '{' enumerator_list comma_opt '}'
    19271960                { $$ = 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 ); }
    19281964        | enum_type_nobody
    19291965        ;
    19301966
    19311967enum_type_nobody:                                                                               // enum - {...}
    1932         ENUM attribute_list_opt no_attr_identifier_or_type_name
     1968        ENUM attribute_list_opt no_attr_identifier
    19331969                {
    19341970                        typedefTable.makeTypedef( *$3 );
    19351971                        $$ = 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 );
    19361977                }
    19371978        ;
     
    19511992        ;
    19521993
    1953 cfa_parameter_type_list_opt:                                                    // CFA, abstract + real
     1994cfa_parameter_ellipsis_list_opt:                                                        // CFA, abstract + real
    19541995        // empty
    19551996                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     
    20842125                { $$ = $2; }
    20852126        | '=' VOID
    2086                 { $$ = nullptr; }
     2127                { $$ = new InitializerNode( true ); }
    20872128        | ATassign initializer
    20882129                { $$ = $2->set_maybeConstructed( false ); }
     
    21612202type_parameter_list:                                                                    // CFA
    21622203        type_parameter
    2163                 { $$ = $1; }
    21642204        | type_parameter_list ',' type_parameter
    21652205                { $$ = $1->appendList( $3 ); }
     
    21752215type_parameter:                                                                                 // CFA
    21762216        type_class no_attr_identifier_or_type_name
    2177                 { typedefTable.addToEnclosingScope( *$2, TYPEDEFname ); }
     2217                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    21782218          type_initializer_opt assertion_list_opt
    21792219                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
     
    22092249        '|' no_attr_identifier_or_type_name '(' type_list ')'
    22102250                { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
    2211         | '|' '{' push trait_declaration_list '}'
     2251        | '|' '{' push trait_declaration_list pop '}'
    22122252                { $$ = $4; }
    2213         | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list '}' '(' type_list ')'
    2214                 { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
     2253        // | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' '(' type_list ')'
     2254        //      { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
    22152255        ;
    22162256
     
    22442284        no_attr_identifier_or_type_name
    22452285                {
    2246                         typedefTable.addToEnclosingScope( *$1, TYPEDEFname );
     2286                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    22472287                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    22482288                }
    2249         | no_attr_identifier_or_type_name '(' push type_parameter_list pop ')'
    2250                 {
    2251                         typedefTable.addToEnclosingScope( *$1, TYPEGENname );
    2252                         $$ = DeclarationNode::newTypeDecl( $1, $4 );
     2289        | no_attr_identifier_or_type_name '(' type_parameter_list ')'
     2290                {
     2291                        typedefTable.addToEnclosingScope( *$1, TYPEGENname, "11" );
     2292                        $$ = DeclarationNode::newTypeDecl( $1, $3 );
    22532293                }
    22542294        ;
    22552295
    22562296trait_specifier:                                                                                // CFA
    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 ); }
     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 ); }
    22612301        ;
    22622302
    22632303trait_declaration_list:                                                                 // CFA
    22642304        trait_declaration
    2265         | trait_declaration_list push trait_declaration
    2266                 { $$ = $1->appendList( $3 ); }
     2305        | trait_declaration_list pop push trait_declaration
     2306                { $$ = $1->appendList( $4 ); }
    22672307        ;
    22682308
    22692309trait_declaration:                                                                              // CFA
    2270         cfa_trait_declaring_list pop ';'
    2271         | trait_declaring_list pop ';'
     2310        cfa_trait_declaring_list ';'
     2311        | trait_declaring_list ';'
    22722312        ;
    22732313
     
    22892329
    22902330translation_unit:
    2291         // empty
    2292                 {}                                                                                              // empty input file
     2331        // empty, input file
    22932332        | external_definition_list
    22942333                { parseTree = parseTree ? parseTree->appendList( $1 ) : $1;     }
     
    22962335
    22972336external_definition_list:
    2298         external_definition
     2337        push external_definition pop
     2338                { $$ = $2; }
    22992339        | external_definition_list
    23002340                { forall = xxx; }
    2301           push external_definition
     2341          push external_definition pop
    23022342                { $$ = $1 ? $1->appendList( $4 ) : $4; }
    23032343        ;
     
    23092349        ;
    23102350
     2351up:
     2352                { typedefTable.up(); }
     2353        ;
     2354
     2355down:
     2356                { typedefTable.down(); }
     2357        ;
     2358
    23112359external_definition:
    23122360        declaration
    23132361        | external_function_definition
     2362        | EXTENSION external_definition                                         // GCC, multiple __extension__ allowed, meaning unknown
     2363                {
     2364                        distExt( $2 );                                                          // mark all fields in list
     2365                        $$ = $2;
     2366                }
    23142367        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    23152368                {
     
    23212374                        linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
    23222375                }
    2323           '{' external_definition_list_opt '}'
     2376          '{' up external_definition_list_opt down '}'
    23242377                {
    23252378                        linkage = linkageStack.top();
    23262379                        linkageStack.pop();
    2327                         $$ = $5;
    2328                 }
    2329         | EXTENSION external_definition                                         // GCC, multiple __extension__ allowed, meaning unknown
    2330                 {
    2331                         distExt( $2 );                                                          // mark all fields in list
    2332                         $$ = $2;
     2380                        $$ = $6;
    23332381                }
    23342382        | type_qualifier_list
    2335                 { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
    2336           push '{' external_definition_list '}'                         // CFA, namespace
     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
    23372388                {
    23382389                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    23462397                }
    23472398        | declaration_qualifier_list
    2348                 { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
    2349           push '{' external_definition_list '}'                         // CFA, namespace
     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
    23502404                {
    23512405                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    23602414        | declaration_qualifier_list type_qualifier_list
    23612415                {
    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
     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
    23662420                {
    23672421                        for ( DeclarationNode * iter = $6; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     
    23872441        | function_declarator compound_statement
    23882442                { $$ = $1->addFunctionBody( $2 ); }
    2389         | KR_function_declarator KR_declaration_list_opt compound_statement
     2443        | KR_function_declarator KR_parameter_list_opt compound_statement
    23902444                { $$ = $1->addOldDeclList( $2 )->addFunctionBody( $3 ); }
    23912445        ;
     
    24272481
    24282482                // Old-style K&R function definition, OBSOLESCENT (see 4)
    2429         | declaration_specifier KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
     2483        | declaration_specifier KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
    24302484                {
    24312485                        rebindForall( $1, $2 );
     
    24332487                }
    24342488                // handles default int return type, OBSOLESCENT (see 1)
    2435         | type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
     2489        | type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
    24362490                { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
    24372491                // handles default int return type, OBSOLESCENT (see 1)
    2438         | declaration_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
     2492        | declaration_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
    24392493                { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
    24402494                // handles default int return type, OBSOLESCENT (see 1)
    2441         | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
     2495        | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
    24422496                { $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 ); }
    24432497        ;
     
    26842738        typedef
    26852739                // hide type name in enclosing scope by variable name
    2686                 { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER ); }
     2740                { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "ID" ); }
    26872741        | '(' paren_type ')'
    26882742                { $$ = $2; }
     
    29743028        '[' ']'
    29753029                { $$ = DeclarationNode::newArray( 0, 0, false ); }
    2976         // multi_array_dimension handles the '[' '*' ']' case
     3030                // multi_array_dimension handles the '[' '*' ']' case
    29773031        | '[' push type_qualifier_list '*' pop ']'                      // remaining C99
    29783032                { $$ = DeclarationNode::newVarArray( $3 ); }
    29793033        | '[' push type_qualifier_list pop ']'
    29803034                { $$ = DeclarationNode::newArray( 0, $3, false ); }
    2981         // multi_array_dimension handles the '[' assignment_expression ']' case
     3035                // multi_array_dimension handles the '[' assignment_expression ']' case
    29823036        | '[' push type_qualifier_list assignment_expression pop ']'
    29833037                { $$ = DeclarationNode::newArray( $4, $3, false ); }
     
    31153169//
    31163170//              cfa_abstract_tuple identifier_or_type_name
    3117 //              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_type_list_opt ')'
     3171//              '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
    31183172//
    31193173// since a function return type can be syntactically identical to a tuple type:
     
    31743228        '[' push cfa_abstract_parameter_list pop ']'
    31753229                { $$ = 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; }
    31763234        ;
    31773235
    31783236cfa_abstract_function:                                                                  // CFA
    3179 //      '[' ']' '(' cfa_parameter_type_list_opt ')'
     3237//      '[' ']' '(' cfa_parameter_ellipsis_list_opt ')'
    31803238//              { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
    3181         cfa_abstract_tuple '(' push cfa_parameter_type_list_opt pop ')'
     3239        cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')'
    31823240                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    3183         | cfa_function_return '(' push cfa_parameter_type_list_opt pop ')'
     3241        | cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')'
    31843242                { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
    31853243        ;
     
    32123270
    32133271%%
     3272
    32143273// ----end of grammar----
    32153274
  • TabularUnified src/ResolvExpr/Alternative.cc

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

    r0182bfa r28f3a19  
    9898                void postvisit( InitExpr * initExpr );
    9999                void postvisit( DeletedExpr * delExpr );
     100                void postvisit( GenericExpr * genExpr );
    100101
    101102                /// Adds alternatives for anonymous members
     
    175176                                                selected[ mangleName ] = current;
    176177                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    177                                                 PRINT(
    178                                                         std::cerr << "marking ambiguous" << std::endl;
    179                                                 )
    180                                                 mapPlace->second.isAmbiguous = true;
     178                                                // if one of the candidates contains a deleted identifier, can pick the other, since
     179                                                // deleted expressions should not be ambiguous if there is another option that is at least as good
     180                                                if ( findDeletedExpr( candidate->expr ) ) {
     181                                                        // do nothing
     182                                                        PRINT( std::cerr << "candidate is deleted" << std::endl; )
     183                                                } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
     184                                                        PRINT( std::cerr << "current is deleted" << std::endl; )
     185                                                        selected[ mangleName ] = current;
     186                                                } else {
     187                                                        PRINT(
     188                                                                std::cerr << "marking ambiguous" << std::endl;
     189                                                        )
     190                                                        mapPlace->second.isAmbiguous = true;
     191                                                }
    181192                                        } else {
    182193                                                PRINT(
     
    298309                // 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
    299310                Expression* aggrExpr = alt.expr->clone();
    300                 alt.env.apply( aggrExpr->get_result() );
    301                 Type * aggrType = aggrExpr->get_result();
     311                alt.env.apply( aggrExpr->result );
     312                Type * aggrType = aggrExpr->result;
    302313                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    303314                        aggrType = aggrType->stripReferences();
     
    305316                }
    306317
    307                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
     318                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    308319                        addAggMembers( structInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
    309                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
     320                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    310321                        addAggMembers( unionInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
    311322                } // if
     
    317328                aggInst->lookup( name, members );
    318329
    319                 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    320                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    321                                 alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
    322                                 renameTypes( alternatives.back().expr );
    323                                 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     330                for ( Declaration * decl : members ) {
     331                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     333                                // can't construct in place and use vector::back
     334                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     335                                renameTypes( newAlt.expr );
     336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     337                                alternatives.push_back( std::move(newAlt) );
    324338                        } else {
    325339                                assert( false );
     
    331345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    332346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    333                         // xxx - this should be improved by memoizing the value of constant exprs
    334                         // during parsing and reusing that information here.
    335                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    336                         int val = 0;
     347                        auto val = constantExpr->intValue();
    337348                        std::string tmp;
    338                         if ( ss >> val && ! (ss >> tmp) ) {
    339                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    340                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
    341                                 } // if
     349                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     350                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    342351                        } // if
    343                 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
    344                         // xxx - temporary hack until 0/1 are int constants
    345                         if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
    346                                 std::stringstream ss( nameExpr->get_name() );
    347                                 int val;
    348                                 ss >> val;
    349                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
    350                         }
    351352                } // if
    352353        }
     
    435436                                        return Cost::infinity;
    436437                                }
     438                        }
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
     440                                // default arguments should be free - don't include conversion cost.
     441                                // Unwrap them here because they are not relevant to the rest of the system.
     442                                *actualExpr = def->expr;
     443                                ++formal;
     444                                continue;
    437445                        }
    438446                        Type * formalType = (*formal)->get_type();
     
    604612        ConstantExpr* getDefaultValue( Initializer* init ) {
    605613                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    606                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    607                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
     614                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
     615                                return dynamic_cast<ConstantExpr*>( ce->arg );
     616                        } else {
     617                                return dynamic_cast<ConstantExpr*>( si->value );
    608618                        }
    609619                }
     
    866876                                                                indexer ) ) {
    867877                                                        results.emplace_back(
    868                                                                 i, cnstExpr, move(env), move(need), move(have),
     878                                                                i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    869879                                                                move(openVars), nextArg, nTuples );
    870880                                                }
     
    10581068                funcFinder.findWithAdjustment( untypedExpr->function );
    10591069                // if there are no function alternatives, then proceeding is a waste of time.
     1070                // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    10601071                if ( funcFinder.alternatives.empty() ) return;
    10611072
     
    10851096                        argExpansions.emplace_back();
    10861097                        auto& argE = argExpansions.back();
    1087                         argE.reserve( arg.alternatives.size() );
     1098                        // argE.reserve( arg.alternatives.size() );
    10881099
    10891100                        for ( const Alternative& actual : arg ) {
     
    11081119                                                        std::back_inserter( candidates ) );
    11091120                                        }
    1110                                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    1111                                         if ( const EqvClass *eqvClass = func->env.lookup( typeInst->get_name() ) ) {
     1121                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     1122                                        if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) {
    11121123                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) {
    11131124                                                        Alternative newFunc( *func );
     
    13641375                        Cost cost = Cost::zero;
    13651376                        Expression * newExpr = data.combine( cost );
    1366                         alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
     1377
     1378                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     1379                        // can't construct in place and use vector::back
     1380                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13671381                        PRINT(
    13681382                                std::cerr << "decl is ";
     
    13731387                                std::cerr << std::endl;
    13741388                        )
    1375                         renameTypes( alternatives.back().expr );
    1376                         addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1389                        renameTypes( newAlt.expr );
     1390                        addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1391                        alternatives.push_back( std::move(newAlt) );
    13771392                } // for
    13781393        }
     
    17411756                assertf( false, "AlternativeFinder should never see a DeletedExpr." );
    17421757        }
     1758
     1759        void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
     1760                assertf( false, "_Generic is not yet supported." );
     1761        }
    17431762} // namespace ResolvExpr
    17441763
  • TabularUnified src/ResolvExpr/CommonType.cc

    r0182bfa r28f3a19  
    2424#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2525#include "SynTree/Visitor.h"             // for Visitor
    26 #include "Unify.h"                       // for unifyExact, bindVar, WidenMode
     26#include "Unify.h"                       // for unifyExact, WidenMode
    2727#include "typeops.h"                     // for isFtype
    2828
     
    176176        }
    177177
    178         static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
     178        static const BasicType::Kind combinedType[][ 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 */
    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, },
     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 },
    204206        };
     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        );
    205211
    206212        CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     
    232238                                AssertionSet need, have;
    233239                                WidenMode widen( widenFirst, widenSecond );
    234                                 if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
     240                                if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    235241                        }
    236242                }
  • TabularUnified src/ResolvExpr/ConversionCost.cc

    r0182bfa r28f3a19  
    229229*/
    230230
    231         static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
    232         /* 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 */
    233                 /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,     },
    234                 /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
    235                 /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
    236                 /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,      },
    237                 /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,      },
    238                 /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,      },
    239                 /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,      },
    240                 /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
    241                 /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
    242                 /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,      },
    243                 /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,      },
    244                 /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,      },
    245 
    246                 /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,     },
    247                 /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,     },
    248                 /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,     },
    249                 /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,     },
    250                 /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,     },
    251                 /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,     },
    252                 /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,     },
    253                 /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,     },
    254                 /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,     },
    255 
    256                 /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,      },
    257                 /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,      },
     231        static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
     232        /* 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 */
     233                /* 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},
     234                /* 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},
     235                /* 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},
     236                /* 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},
     237                /* 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},
     238                /* 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},
     239                /* 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},
     240                /* 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},
     241                /* 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},
     242                /* 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},
     243                /* 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},
     244                /* 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},
     245
     246                /* 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},
     247                /* 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},
     248                /* 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},
     249                /* 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},
     250                /* 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},
     251                /* 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},
     252                /* 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},
     253                /* 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},
     254                /* 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},
     255
     256                /* 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},
     257                /* 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},
     258
     259                /* 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},
     260                /* 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},
    258261        };
     262        static_assert(
     263                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
     264                "Each basic type kind should have a corresponding row in the cost matrix"
     265        );
     266
    259267
    260268        void ConversionCost::postvisit( VoidType * ) {
  • TabularUnified src/ResolvExpr/ExplodedActual.h

    r0182bfa r28f3a19  
    3131
    3232                ExplodedActual() : env(), cost(Cost::zero), exprs() {}
    33 
    3433                ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
     34                ExplodedActual(ExplodedActual&&) = default;
     35                ExplodedActual& operator= (ExplodedActual&&) = default;
    3536        };
    3637}
  • TabularUnified src/ResolvExpr/Resolver.cc

    r0182bfa r28f3a19  
    211211                        if ( findDeletedExpr( choice.expr ) ) {
    212212                                trace( choice.expr );
    213                                 SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
     213                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    214214                        }
    215215                        alt = std::move( choice );
     
    246246
    247247                auto untyped = new CastExpr{ expr }; // cast to void
     248                untyped->location = expr->location;
    248249
    249250                // set up and resolve expression cast to void
     
    271272        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    272273                assert( untyped && type );
     274                // transfer location to generated cast for error purposes
     275                CodeLocation location = untyped->location;
    273276                untyped = new CastExpr( untyped, type );
     277                untyped->location = location;
    274278                findSingleExpression( untyped, indexer );
    275279                removeExtraneousCast( untyped, indexer );
     
    574578
    575579                                                        // Make sure we don't widen any existing bindings
    576                                                         for ( auto & i : resultEnv ) {
    577                                                                 i.allowWidening = false;
    578                                                         }
    579 
     580                                                        resultEnv.forbidWidening();
     581                                                       
    580582                                                        // Find any unbound type variables
    581583                                                        resultEnv.extractOpenVars( openVars );
  • TabularUnified src/ResolvExpr/Resolver.h

    r0182bfa r28f3a19  
    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 );
    3840} // namespace ResolvExpr
    3941
  • TabularUnified src/ResolvExpr/TypeEnvironment.cc

    r0182bfa r28f3a19  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 12:23:36 2015
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2424#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
    2525#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
     26#include "Tuples/Tuples.h"             // for isTtype
    2627#include "TypeEnvironment.h"
     28#include "typeops.h"                   // for occurs
     29#include "Unify.h"                     // for unifyInexact
    2730
    2831namespace ResolvExpr {
     
    4649
    4750        void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {
     51                initialize( src, dest, src.type );
     52        }
     53
     54        void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {
    4855                dest.vars = src.vars;
    49                 dest.type = maybeClone( src.type );
     56                dest.type = maybeClone( ty );
    5057                dest.allowWidening = src.allowWidening;
    5158                dest.data = src.data;
    5259        }
    5360
    54         EqvClass::EqvClass() : type( 0 ), allowWidening( true ) {
     61        EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) {
    5562        }
    5663
    5764        EqvClass::EqvClass( const EqvClass &other ) {
    5865                initialize( other, *this );
     66        }
     67
     68        EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {
     69                initialize( other, *this, ty );
     70        }
     71
     72        EqvClass::EqvClass( EqvClass &&other )
     73        : vars{std::move(other.vars)}, type{other.type},
     74          allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
     75                  other.type = nullptr;
    5976        }
    6077
     
    6481                return *this;
    6582        }
     83
     84        EqvClass &EqvClass::operator=( EqvClass &&other ) {
     85                if ( this == &other ) return *this;
     86               
     87                vars = std::move(other.vars);
     88                type = other.type;
     89                allowWidening = std::move(other.allowWidening);
     90                data = std::move(other.data);
     91
     92                return *this;
     93        }
     94
     95        void EqvClass::set_type( Type* ty ) { type = ty; }
    6696
    6797        void EqvClass::print( std::ostream &os, Indenter indent ) const {
     
    81111        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    82112                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    83                         if ( i->vars.find( var ) != i->vars.end() ) {
    84 ///       std::cout << var << " is in class ";
    85 ///       i->print( std::cout );
    86                                 return &*i;
    87                         }
    88 ///     std::cout << var << " is not in class ";
    89 ///     i->print( std::cout );
     113                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
    90114                } // for
    91115                return nullptr;
     
    105129        }
    106130
    107         void TypeEnvironment::add( const EqvClass &eqvClass ) {
    108                 filterOverlappingClasses( env, eqvClass );
    109                 env.push_back( eqvClass );
    110         }
    111 
    112131        void TypeEnvironment::add( EqvClass &&eqvClass ) {
    113132                filterOverlappingClasses( env, eqvClass );
     
    120139                        newClass.vars.insert( (*i)->get_name() );
    121140                        newClass.data = TypeDecl::Data{ (*i) };
    122                         env.push_back( newClass );
     141                        env.push_back( std::move(newClass) );
    123142                } // for
    124143        }
     
    134153                        // transition to TypeSubstitution
    135154                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
    136                         add( newClass );
     155                        add( std::move(newClass) );
    137156                }
    138157        }
     
    141160                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    142161                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    143 ///       std::cerr << "adding " << *theVar;
    144162                                if ( theClass->type ) {
    145 ///         std::cerr << " bound to ";
    146 ///         theClass->type->print( std::cerr );
    147 ///         std::cerr << std::endl;
    148163                                        sub.add( *theVar, theClass->type );
    149164                                } else if ( theVar != theClass->vars.begin() ) {
    150165                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
    151 ///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    152166                                        sub.add( *theVar, newTypeInst );
    153167                                } // if
    154168                        } // for
    155169                } // for
    156 ///   std::cerr << "input env is:" << std::endl;
    157 ///   print( std::cerr, 8 );
    158 ///   std::cerr << "sub is:" << std::endl;
    159 ///   sub.print( std::cerr, 8 );
    160170                sub.normalize();
    161171        }
    162172
    163173        void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
    164                 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    165                         i->print( os, indent );
     174                for ( const EqvClass & theClass : env ) {
     175                        theClass.print( os, indent );
    166176                } // for
    167177        }
     
    169179        std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    170180                for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
    171                         if ( i->vars.find( var ) == i->vars.end() ) {
    172                                 return i;
    173                         } // if
     181                        if ( i->vars.count( var ) ) return i;
    174182                } // for
    175183                return env.end();
     
    178186        void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) {
    179187                env.insert( env.end(), second.env.begin(), second.env.end() );
    180         }
    181 
    182         void TypeEnvironment::combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ) {
    183                 TypeEnvironment secondCopy( second );
    184                 for ( std::list< EqvClass >::iterator firstClass = env.begin(); firstClass != env.end(); ++firstClass ) {
    185                         EqvClass &newClass = *firstClass;
    186                         std::set< std::string > newVars;
    187                         for ( std::set< std::string >::const_iterator var = firstClass->vars.begin(); var != firstClass->vars.end(); ++var ) {
    188                                 std::list< EqvClass >::iterator secondClass = secondCopy.internal_lookup( *var );
    189                                 if ( secondClass != secondCopy.env.end() ) {
    190                                         newVars.insert( secondClass->vars.begin(), secondClass->vars.end() );
    191                                         if ( secondClass->type ) {
    192                                                 if ( newClass.type ) {
    193                                                         newClass.type = combineFunc( newClass.type, secondClass->type );
    194                                                         newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening;
    195                                                 } else {
    196                                                         newClass.type = secondClass->type->clone();
    197                                                         newClass.allowWidening = secondClass->allowWidening;
    198                                                 } // if
    199                                         } // if
    200                                         secondCopy.env.erase( secondClass );
    201                                 } // if
    202                         } // for
    203                         newClass.vars.insert( newVars.begin(), newVars.end() );
    204                 } // for
    205                 for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) {
    206                         env.push_back( *secondClass );
    207                 } // for
    208188        }
    209189
     
    227207        }
    228208
     209        bool isFtype( Type *type ) {
     210                if ( dynamic_cast< FunctionType* >( type ) ) {
     211                        return true;
     212                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
     213                        return typeInst->get_isFtype();
     214                } // if
     215                return false;
     216        }
     217
     218        bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
     219                switch ( data.kind ) {
     220                  case TypeDecl::Dtype:
     221                        // to bind to an object type variable, the type must not be a function type.
     222                        // if the type variable is specified to be a complete type then the incoming
     223                        // type must also be complete
     224                        // xxx - should this also check that type is not a tuple type and that it's not a ttype?
     225                        return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
     226                  case TypeDecl::Ftype:
     227                        return isFtype( type );
     228                  case TypeDecl::Ttype:
     229                        // ttype unifies with any tuple type
     230                        return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
     231                } // switch
     232                return false;
     233        }
     234
     235        bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     236               
     237                // remove references from other, so that type variables can only bind to value types
     238                bindTo = bindTo->stripReferences();
     239                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
     240                assert( tyvar != openVars.end() );
     241                if ( ! tyVarCompatible( tyvar->second, bindTo ) ) {
     242                        return false;
     243                } // if
     244                if ( occurs( bindTo, typeInst->get_name(), *this ) ) {
     245                        return false;
     246                } // if
     247                auto curClass = internal_lookup( typeInst->get_name() );
     248                if ( curClass != env.end() ) {
     249                        if ( curClass->type ) {
     250                                Type *common = 0;
     251                                // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
     252                                Type *newType = curClass->type->clone();
     253                                newType->get_qualifiers() = typeInst->get_qualifiers();
     254                                if ( unifyInexact( newType, bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     255                                        if ( common ) {
     256                                                common->get_qualifiers() = Type::Qualifiers{};
     257                                                curClass->set_type( common );
     258                                        } // if
     259                                } else return false;
     260                        } else {
     261                                Type* newType = bindTo->clone();
     262                                newType->get_qualifiers() = Type::Qualifiers{};
     263                                curClass->set_type( newType );
     264                                curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     265                        } // if
     266                } else {
     267                        EqvClass newClass;
     268                        newClass.vars.insert( typeInst->get_name() );
     269                        newClass.type = bindTo->clone();
     270                        newClass.type->get_qualifiers() = Type::Qualifiers();
     271                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     272                        newClass.data = data;
     273                        env.push_back( std::move(newClass) );
     274                } // if
     275                return true;
     276        }
     277
     278        bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     279
     280                auto class1 = internal_lookup( var1->get_name() );
     281                auto class2 = internal_lookup( var2->get_name() );
     282               
     283                // exit early if variables already bound together
     284                if ( class1 != env.end() && class1 == class2 ) {
     285                        class1->allowWidening &= widenMode;
     286                        return true;
     287                }
     288
     289                bool widen1 = false, widen2 = false;
     290                const Type *type1 = nullptr, *type2 = nullptr;
     291
     292                // check for existing bindings, perform occurs check
     293                if ( class1 != env.end() ) {
     294                        if ( class1->type ) {
     295                                if ( occurs( class1->type, var2->get_name(), *this ) ) return false;
     296                                type1 = class1->type;
     297                        } // if
     298                        widen1 = widenMode.widenFirst && class1->allowWidening;
     299                } // if
     300                if ( class2 != env.end() ) {
     301                        if ( class2->type ) {
     302                                if ( occurs( class2->type, var1->get_name(), *this ) ) return false;
     303                                type2 = class2->type;
     304                        } // if
     305                        widen2 = widenMode.widenSecond && class2->allowWidening;
     306                } // if
     307
     308                if ( type1 && type2 ) {
     309                        // both classes bound, merge if bound types can be unified
     310                        Type *newType1 = type1->clone(), *newType2 = type2->clone();
     311                        WidenMode newWidenMode{ widen1, widen2 };
     312                        Type *common = 0;
     313                        if ( unifyInexact( newType1, newType2, *this, need, have, openVars, newWidenMode, indexer, common ) ) {
     314                                class1->vars.insert( class2->vars.begin(), class2->vars.end() );
     315                                class1->allowWidening = widen1 && widen2;
     316                                if ( common ) {
     317                                        common->get_qualifiers() = Type::Qualifiers{};
     318                                        class1->set_type( common );
     319                                }
     320                                env.erase( class2 );
     321                        } else return false;
     322                } else if ( class1 != env.end() && class2 != env.end() ) {
     323                        // both classes exist, at least one unbound, merge unconditionally
     324                        if ( type1 ) {
     325                                class1->vars.insert( class2->vars.begin(), class2->vars.end() );
     326                                class1->allowWidening = widen1;
     327                                env.erase( class2 );
     328                        } else {
     329                                class2->vars.insert( class1->vars.begin(), class1->vars.end() );
     330                                class2->allowWidening = widen2;
     331                                env.erase( class1 );
     332                        } // if
     333                } else if ( class1 != env.end() ) {
     334                        // var2 unbound, add to class1
     335                        class1->vars.insert( var2->get_name() );
     336                        class1->allowWidening = widen1;
     337                } else if ( class2 != env.end() ) {
     338                        // var1 unbound, add to class2
     339                        class2->vars.insert( var1->get_name() );
     340                        class2->allowWidening = widen2;
     341                } else {
     342                        // neither var bound, create new class
     343                        EqvClass newClass;
     344                        newClass.vars.insert( var1->get_name() );
     345                        newClass.vars.insert( var2->get_name() );
     346                        newClass.allowWidening = widen1 && widen2;
     347                        newClass.data = data;
     348                        env.push_back( std::move(newClass) );
     349                } // if
     350                return true;
     351        }
     352
     353        void TypeEnvironment::forbidWidening() {
     354                for ( EqvClass& c : env ) c.allowWidening = false;
     355        }
     356
    229357        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
    230358                env.print( out );
  • TabularUnified src/ResolvExpr/TypeEnvironment.h

    r0182bfa r28f3a19  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:45 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2121#include <set>                         // for set
    2222#include <string>                      // for string
     23#include <utility>                     // for move, swap
     24
     25#include "WidenMode.h"                 // for WidenMode
    2326
    2427#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
     
    7780
    7881                void initialize( const EqvClass &src, EqvClass &dest );
     82                void initialize( const EqvClass &src, EqvClass &dest, const Type *ty );
    7983                EqvClass();
    8084                EqvClass( const EqvClass &other );
     85                EqvClass( const EqvClass &other, const Type *ty );
     86                EqvClass( EqvClass &&other );
    8187                EqvClass &operator=( const EqvClass &other );
     88                EqvClass &operator=( EqvClass &&other );
    8289                void print( std::ostream &os, Indenter indent = {} ) const;
     90
     91                /// Takes ownership of `ty`, freeing old `type`
     92                void set_type(Type* ty);
    8393        };
    8494
     
    8696          public:
    8797                const EqvClass* lookup( const std::string &var ) const;
    88                 void add( const EqvClass &eqvClass );
     98          private:
    8999                void add( EqvClass &&eqvClass  );
     100          public:
    90101                void add( const Type::ForallList &tyDecls );
    91102                void add( const TypeSubstitution & sub );
     
    95106                bool isEmpty() const { return env.empty(); }
    96107                void print( std::ostream &os, Indenter indent = {} ) const;
    97                 void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     108                // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
    98109                void simpleCombine( const TypeEnvironment &second );
    99110                void extractOpenVars( OpenVarSet &openVars ) const;
     
    104115                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    105116
    106                 typedef std::list< EqvClass >::iterator iterator;
    107                 iterator begin() { return env.begin(); }
    108                 iterator end() { return env.end(); }
    109                 typedef std::list< EqvClass >::const_iterator const_iterator;
    110                 const_iterator begin() const { return env.begin(); }
    111                 const_iterator end() const { return env.end(); }
     117                /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
     118                /// the class if needed. Returns false on failure.
     119                bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     120               
     121                /// Binds the type classes represented by `var1` and `var2` together; will add
     122                /// one or both classes if needed. Returns false on failure.
     123                bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     124
     125                /// Disallows widening for all bindings in the environment
     126                void forbidWidening();
     127
     128                using iterator = std::list< EqvClass >::const_iterator;
     129                iterator begin() const { return env.begin(); }
     130                iterator end() const { return env.end(); }
     131
    112132          private:
    113133                std::list< EqvClass > env;
     134               
    114135                std::list< EqvClass >::iterator internal_lookup( const std::string &var );
    115136        };
  • TabularUnified src/ResolvExpr/Unify.cc

    r0182bfa r28f3a19  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 16:22:54 2017
    13 // Update Count     : 42
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 43
    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 tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
    134                 switch ( data.kind ) {
    135                   case TypeDecl::Dtype:
    136                         // to bind to an object type variable, the type must not be a function type.
    137                         // if the type variable is specified to be a complete type then the incoming
    138                         // type must also be complete
    139                         // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    140                         return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
    141                   case TypeDecl::Ftype:
    142                         return isFtype( type );
    143                   case TypeDecl::Ttype:
    144                         // ttype unifies with any tuple type
    145                         return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
    146                 } // switch
    147                 return false;
    148         }
    149 
    150         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 ) {
    151                 // remove references from other, so that type variables can only bind to value types
    152                 other = other->stripReferences();
    153                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    154                 assert( tyvar != openVars.end() );
    155                 if ( ! tyVarCompatible( tyvar->second, other ) ) {
    156                         return false;
    157                 } // if
    158                 if ( occurs( other, typeInst->get_name(), env ) ) {
    159                         return false;
    160                 } // if
    161                 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
    162                         if ( curClass->type ) {
    163                                 Type *common = 0;
    164                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    165                                 Type* newType = curClass->type->clone();
    166                                 newType->get_qualifiers() = typeInst->get_qualifiers();
    167                                 if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    168                                         if ( common ) {
    169                                                 common->get_qualifiers() = Type::Qualifiers();
    170                                                 EqvClass newClass = *curClass;
    171                                                 newClass.type = common;
    172                                                 env.add( std::move(newClass) );
    173                                         } // if
    174                                         return true;
    175                                 } else {
    176                                         return false;
    177                                 } // if
    178                         } else {
    179                                 EqvClass newClass = *curClass;
    180                                 newClass.type = other->clone();
    181                                 newClass.type->get_qualifiers() = Type::Qualifiers();
    182                                 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    183                                 env.add( std::move(newClass) );
    184                         } // if
    185                 } else {
    186                         EqvClass newClass;
    187                         newClass.vars.insert( typeInst->get_name() );
    188                         newClass.type = other->clone();
    189                         newClass.type->get_qualifiers() = Type::Qualifiers();
    190                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    191                         newClass.data = data;
    192                         env.add( newClass );
    193                 } // if
    194                 return true;
    195         }
    196 
    197         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 ) {
    198                 bool result = true;
    199                 const EqvClass *class1 = env.lookup( var1->get_name() );
    200                 const EqvClass *class2 = env.lookup( var2->get_name() );
    201                 bool widen1 = false, widen2 = false;
    202                 Type *type1 = nullptr, *type2 = nullptr;
    203 
    204                 if ( class1 ) {
    205                         if ( class1->type ) {
    206                                 if ( occurs( class1->type, var2->get_name(), env ) ) {
    207                                         return false;
    208                                 } // if
    209                                 type1 = class1->type->clone();
    210                         } // if
    211                         widen1 = widenMode.widenFirst && class1->allowWidening;
    212                 } // if
    213                 if ( class2 ) {
    214                         if ( class2->type ) {
    215                                 if ( occurs( class2->type, var1->get_name(), env ) ) {
    216                                         return false;
    217                                 } // if
    218                                 type2 = class2->type->clone();
    219                         } // if
    220                         widen2 = widenMode.widenSecond && class2->allowWidening;
    221                 } // if
    222 
    223                 if ( type1 && type2 ) {
    224 //    std::cerr << "has type1 && type2" << std::endl;
    225                         WidenMode newWidenMode ( widen1, widen2 );
    226                         Type *common = 0;
    227                         if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
    228                                 EqvClass newClass1 = *class1;
    229                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    230                                 newClass1.allowWidening = widen1 && widen2;
    231                                 if ( common ) {
    232                                         common->get_qualifiers() = Type::Qualifiers();
    233                                         newClass1.type = common;
    234                                 } // if
    235                                 env.add( std::move(newClass1) );
    236                         } else {
    237                                 result = false;
    238                         } // if
    239                 } else if ( class1 && class2 ) {
    240                         if ( type1 ) {
    241                                 EqvClass newClass1 = *class1;
    242                                 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
    243                                 newClass1.allowWidening = widen1;
    244                                 env.add( std::move(newClass1) );
    245                         } else {
    246                                 EqvClass newClass2 = *class2;
    247                                 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
    248                                 newClass2.allowWidening = widen2;
    249                                 env.add( std::move(newClass2) );
    250                         } // if
    251                 } else if ( class1 ) {
    252                         EqvClass newClass1 = *class1;
    253                         newClass1.vars.insert( var2->get_name() );
    254                         newClass1.allowWidening = widen1;
    255                         env.add( std::move(newClass1) );
    256                 } else if ( class2 ) {
    257                         EqvClass newClass2 = *class2;
    258                         newClass2.vars.insert( var1->get_name() );
    259                         newClass2.allowWidening = widen2;
    260                         env.add( std::move(newClass2) );
    261                 } else {
    262                         EqvClass newClass;
    263                         newClass.vars.insert( var1->get_name() );
    264                         newClass.vars.insert( var2->get_name() );
    265                         newClass.allowWidening = widen1 && widen2;
    266                         newClass.data = data;
    267                         env.add( newClass );
    268                 } // if
    269                 return result;
    270         }
    271 
    272124        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    273125                OpenVarSet closedVars;
     
    307159
    308160                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    309                         result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     161                        result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    310162                } else if ( isopen1 ) {
    311                         result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     163                        result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    312164                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
    313                         result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     165                        result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    314166                } else {
    315167                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
  • TabularUnified src/ResolvExpr/Unify.h

    r0182bfa r28f3a19  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 23:09:34 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2121#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2222#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
     23#include "WidenMode.h"            // for WidenMode
    2324
    2425class Type;
     
    2930
    3031namespace 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 );
    4332        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    4433        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    4534        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 );
    4636
    4737        template< typename Iterator1, typename Iterator2 >
  • TabularUnified src/SymTab/Indexer.cc

    r0182bfa r28f3a19  
    106106                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
    107107
    108                 // helpful data structure
     108                // helpful data structure to organize properties for a type
    109109                struct ValueType {
    110                         struct DeclBall {
     110                        struct DeclBall { // properties for this particular decl
    111111                                IdData decl;
    112                                 bool isUserDefinedFunc; // properties for this particular decl
    113                                 bool isDefaultCtor;
    114                                 bool isDtor;
     112                                bool isUserDefinedFunc;
    115113                                bool isCopyFunc;
    116114                        };
    117115                        // 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
    121116                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
    122                         bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found
     117                        BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
    123118                        std::list< DeclBall > decls;
    124119
     
    127122                        ValueType & operator+=( IdData data ) {
    128123                                DeclarationWithType * function = data.id;
    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);
     124                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
     125                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
     126                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
    137127                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    138                                 existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor);
     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                                }
    139133                                return *this;
    140134                        }
     
    148142                for ( auto decl : copy ) {
    149143                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
    150                                 std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
     144                                std::list< DeclarationWithType * > & params = function->type->parameters;
    151145                                assert( ! params.empty() );
    152146                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     
    160154
    161155                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
    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).
     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.
    167162                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    168163                        ValueType & val = pair.second;
    169164                        for ( ValueType::DeclBall ball : val.decls ) {
    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 );
     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                                        }
    178183                                }
     184                                out.push_back( ball.decl );
    179185                        }
    180186                }
     
    471477        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
    472478                // default handling of conflicts is to raise an error
    473                 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr );
     479                addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
    474480        }
    475481
  • TabularUnified src/SymTab/Mangler.cc

    r0182bfa r28f3a19  
    171171                                        "w",    // SignedInt128
    172172                                        "Uw",   // UnsignedInt128
     173                                        "x",   // Float80
     174                                        "y",   // Float128
    173175                                };
     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                                );
    174180
    175181                                printQualifiers( basicType );
     182                                assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) );
    176183                                mangleName << btLetter[ basicType->get_kind() ];
    177184                        }
     
    218225                                GuardValue( inFunctionType );
    219226                                inFunctionType = true;
    220                                 std::list< Type* > returnTypes = getTypes( functionType->get_returnVals() );
     227                                std::list< Type* > returnTypes = getTypes( functionType->returnVals );
    221228                                acceptAll( returnTypes, *visitor );
    222229                                mangleName << "_";
    223                                 std::list< Type* > paramTypes = getTypes( functionType->get_parameters() );
     230                                std::list< Type* > paramTypes = getTypes( functionType->parameters );
    224231                                acceptAll( paramTypes, *visitor );
    225232                                mangleName << "_";
     
    229236                                printQualifiers( refType );
    230237
    231                                 mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name();
     238                                mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
    232239
    233240                                if ( mangleGenericParams ) {
    234                                         std::list< Expression* >& params = refType->get_parameters();
     241                                        std::list< Expression* >& params = refType->parameters;
    235242                                        if ( ! params.empty() ) {
    236243                                                mangleName << "_";
    237244                                                for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
    238245                                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    239                                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str());
    240                                                         maybeAccept( paramType->get_type(), *visitor );
     246                                                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
     247                                                        maybeAccept( paramType->type, *visitor );
    241248                                                }
    242249                                                mangleName << "_";
  • TabularUnified src/SymTab/Validate.cc

    r0182bfa r28f3a19  
    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
    5152#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    5253#include "Common/ScopedMap.h"          // for ScopedMap
     
    7778class SwitchStmt;
    7879
    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
    277278                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
    278279                Concurrency::implementMutexFuncs( translationUnit );
  • TabularUnified src/SynTree/BasicType.cc

    r0182bfa r28f3a19  
    5555          case DoubleImaginary:
    5656          case LongDoubleImaginary:
     57          case Float80:
     58          case Float128:
    5759                return false;
    5860          case NUMBER_OF_BASIC_TYPES:
  • TabularUnified src/SynTree/Declaration.cc

    r0182bfa r28f3a19  
    9292}
    9393
     94
    9495// Local Variables: //
    9596// tab-width: 4 //
  • TabularUnified src/SynTree/Declaration.h

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

    r0182bfa r28f3a19  
    640640
    641641
     642DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
     643        assert( expr->result );
     644        result = expr->result->clone();
     645}
     646DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
     647
     648void 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
     653GenericExpr::Association::Association( Type * type, Expression * expr ) : type( type ), expr( expr ), isDefault( false ) {}
     654GenericExpr::Association::Association( Expression * expr ) : type( nullptr ), expr( expr ), isDefault( true ) {}
     655GenericExpr::Association::Association( const Association & other ) : type( maybeClone( other.type ) ), expr( maybeClone( other.expr ) ), isDefault( other.isDefault ) {}
     656
     657GenericExpr::GenericExpr( Expression * control, const std::list<Association> & assoc ) : Expression(), control( control ), associations( assoc ) {}
     658GenericExpr::GenericExpr( const GenericExpr & other ) : Expression(other), control( maybeClone( other.control ) ), associations( other.associations ) {}
     659GenericExpr::~GenericExpr() {}
     660
     661void 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
    642681// Local Variables: //
    643682// tab-width: 4 //
  • TabularUnified src/SynTree/Expression.h

    r0182bfa r28f3a19  
    833833};
    834834
     835/// expression wrapping the use of a default argument - should never make it past the resolver.
     836class DefaultArgExpr : public Expression {
     837public:
     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
     850class GenericExpr : public Expression {
     851public:
     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
    835876// Local Variables: //
    836877// tab-width: 4 //
  • TabularUnified src/SynTree/Mutator.h

    r0182bfa r28f3a19  
    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;
    9597
    9698        virtual Type * mutate( VoidType * basicType ) = 0;
  • TabularUnified src/SynTree/ReferenceToType.cc

    r0182bfa r28f3a19  
    4646
    4747namespace {
    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 );
     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 );
    5252                        } // if
    5353                } // for
     
    5656
    5757StructInstType::StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct, const std::list< Attribute * > & attributes ) :
    58                 Parent( tq, baseStruct->get_name(), attributes ), baseStruct( baseStruct ) {}
     58                Parent( tq, baseStruct->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->get_members(), name, foundDecls );
     82        doLookup( baseStruct->members, name, foundDecls );
    8383}
    8484
     
    9999
    100100UnionInstType::UnionInstType( const Type::Qualifiers & tq, UnionDecl * baseUnion, const std::list< Attribute * > & attributes ) :
    101                 Parent( tq, baseUnion->get_name(), attributes ), baseUnion( baseUnion ) {}
     101                Parent( tq, baseUnion->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->get_members(), name, foundDecls );
     125        doLookup( baseUnion->members, name, foundDecls );
    126126}
    127127
  • TabularUnified src/SynTree/Statement.cc

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

    r0182bfa r28f3a19  
    213213        Expression *condition;
    214214        Statement *body;
     215        std::list<Statement *> initialization;
    215216        bool isDoWhile;
    216217
    217218        WhileStmt( Expression *condition,
    218                Statement *body, bool isDoWhile = false );
     219               Statement *body, std::list<Statement *> & initialization, bool isDoWhile = false );
    219220        WhileStmt( const WhileStmt &other );
    220221
  • TabularUnified src/SynTree/SynTree.h

    r0182bfa r28f3a19  
    101101class InitExpr;
    102102class DeletedExpr;
     103class DefaultArgExpr;
     104class GenericExpr;
    103105
    104106class Type;
  • TabularUnified src/SynTree/Type.cc

    r0182bfa r28f3a19  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:16:32 2017
    13 // Update Count     : 38
     12// Last Modified On : Fri Jun 22 10:17:19 2018
     13// Update Count     : 39
    1414//
    1515#include "Type.h"
     
    2424using namespace std;
    2525
    26 const char *BasicType::typeNames[BasicType::NUMBER_OF_BASIC_TYPES] = {
     26const char *BasicType::typeNames[] = {
    2727        "_Bool",
    2828        "char",
     
    4848        "__int128",
    4949        "unsigned __int128",
     50        "__float80",
     51        "__float128"
    5052};
     53static_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);
    5157
    5258Type::Type( const Qualifiers &tq, const std::list< Attribute * > & attributes ) : tq( tq ), attributes( attributes ) {}
     
    5864
    5965// These must remain in the same order as the corresponding bit fields.
    60 const char * Type::FuncSpecifiersNames[] = { "inline", "fortran", "_Noreturn" };
     66const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
    6167const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
    6268const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
  • TabularUnified src/SynTree/Type.h

    r0182bfa r28f3a19  
    230230                SignedInt128,
    231231                UnsignedInt128,
     232                Float80,
     233                Float128,
    232234                NUMBER_OF_BASIC_TYPES
    233235        } kind;
  • TabularUnified src/SynTree/Visitor.h

    r0182bfa r28f3a19  
    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;
    9799
    98100        virtual void visit( VoidType * basicType ) = 0;
  • TabularUnified src/benchmark/Makefile.am

    r0182bfa r28f3a19  
    9292
    9393## =========================================================================================================
     94loop$(EXEEXT):
     95        @@BACKEND_CC@ loop.c      -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     96
     97function$(EXEEXT):
     98        @@BACKEND_CC@ function.c  -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     99
     100fetch_add$(EXEEXT):
     101        @@BACKEND_CC@ fetch_add.c -DBENCH_N=500000000  -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     102
     103## =========================================================================================================
    94104ctxswitch$(EXEEXT): \
     105        loop.run                                \
     106        function.run                    \
     107        fetch_add.run                   \
    95108        ctxswitch-pthread.run           \
    96109        ctxswitch-cfa_coroutine.run     \
    97110        ctxswitch-cfa_thread.run        \
     111        ctxswitch-cfa_thread2.run       \
    98112        ctxswitch-upp_coroutine.run     \
    99113        ctxswitch-upp_thread.run        \
     114        -ctxswitch-kos_fibre.run        \
     115        -ctxswitch-kos_fibre2.run       \
    100116        ctxswitch-goroutine.run         \
    101117        ctxswitch-java_thread.run
    102118
     119ctxswitch-pthread$(EXEEXT):
     120        @@BACKEND_CC@ ctxswitch/pthreads.c     -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     121
    103122ctxswitch-cfa_coroutine$(EXEEXT):
    104         @${CC}        ctxswitch/cfa_cor.c   -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     123        @${CC}        ctxswitch/cfa_cor.c      -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    105124
    106125ctxswitch-cfa_thread$(EXEEXT):
    107         @${CC}        ctxswitch/cfa_thrd.c  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     126        @${CC}        ctxswitch/cfa_thrd.c     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     127
     128ctxswitch-cfa_thread2$(EXEEXT):
     129        @${CC}        ctxswitch/cfa_thrd2.c    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    108130
    109131ctxswitch-upp_coroutine$(EXEEXT):
    110         @u++          ctxswitch/upp_cor.cc  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     132        @u++          ctxswitch/upp_cor.cc     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    111133
    112134ctxswitch-upp_thread$(EXEEXT):
    113         @u++          ctxswitch/upp_thrd.cc -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    114 
    115 ctxswitch-pthread$(EXEEXT):
    116         @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     135        @u++          ctxswitch/upp_thrd.cc    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     136
     137ctxswitch-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
     140ctxswitch-kos_fibre2$(EXEEXT):
     141        @${CXX}       ctxswitch/kos_fibre2.cpp -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
    117142
    118143ctxswitch-goroutine$(EXEEXT):
     
    127152## =========================================================================================================
    128153mutex$(EXEEXT) :\
    129         mutex-function.run      \
    130         mutex-fetch_add.run     \
     154        loop.run                        \
     155        function.run            \
     156        fetch_add.run           \
    131157        mutex-pthread_lock.run  \
    132158        mutex-upp.run           \
     
    135161        mutex-cfa4.run          \
    136162        mutex-java_thread.run
    137 
    138 mutex-function$(EXEEXT):
    139         @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    140 
    141 mutex-fetch_add$(EXEEXT):
    142         @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    143163
    144164mutex-pthread_lock$(EXEEXT):
     
    277297
    278298compile-io$(EXEEXT):
    279         @${CC} -quiet -fsyntax-only -w ../tests/io.c                                    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     299        @${CC} -quiet -fsyntax-only -w ../tests/io1.c                           @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    280300
    281301compile-monitor$(EXEEXT):
    282         @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c            @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     302        @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    283303
    284304compile-operators$(EXEEXT):
     
    289309
    290310compile-typeof$(EXEEXT):
    291         @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                                @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    292 
     311        @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                        @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     312
  • TabularUnified src/benchmark/Makefile.in

    r0182bfa r28f3a19  
    505505        @echo "}"
    506506
     507loop$(EXEEXT):
     508        @@BACKEND_CC@ loop.c      -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     509
     510function$(EXEEXT):
     511        @@BACKEND_CC@ function.c  -DBENCH_N=5000000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     512
     513fetch_add$(EXEEXT):
     514        @@BACKEND_CC@ fetch_add.c -DBENCH_N=500000000  -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     515
    507516ctxswitch$(EXEEXT): \
     517        loop.run                                \
     518        function.run                    \
     519        fetch_add.run                   \
    508520        ctxswitch-pthread.run           \
    509521        ctxswitch-cfa_coroutine.run     \
    510522        ctxswitch-cfa_thread.run        \
     523        ctxswitch-cfa_thread2.run       \
    511524        ctxswitch-upp_coroutine.run     \
    512525        ctxswitch-upp_thread.run        \
     526        -ctxswitch-kos_fibre.run        \
     527        -ctxswitch-kos_fibre2.run       \
    513528        ctxswitch-goroutine.run         \
    514529        ctxswitch-java_thread.run
    515530
     531ctxswitch-pthread$(EXEEXT):
     532        @@BACKEND_CC@ ctxswitch/pthreads.c     -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     533
    516534ctxswitch-cfa_coroutine$(EXEEXT):
    517         @${CC}        ctxswitch/cfa_cor.c   -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     535        @${CC}        ctxswitch/cfa_cor.c      -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    518536
    519537ctxswitch-cfa_thread$(EXEEXT):
    520         @${CC}        ctxswitch/cfa_thrd.c  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     538        @${CC}        ctxswitch/cfa_thrd.c     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     539
     540ctxswitch-cfa_thread2$(EXEEXT):
     541        @${CC}        ctxswitch/cfa_thrd2.c    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    521542
    522543ctxswitch-upp_coroutine$(EXEEXT):
    523         @u++          ctxswitch/upp_cor.cc  -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     544        @u++          ctxswitch/upp_cor.cc     -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    524545
    525546ctxswitch-upp_thread$(EXEEXT):
    526         @u++          ctxswitch/upp_thrd.cc -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    527 
    528 ctxswitch-pthread$(EXEEXT):
    529         @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     547        @u++          ctxswitch/upp_thrd.cc    -DBENCH_N=50000000  -I. -nodebug -lrt -quiet             ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     548
     549ctxswitch-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
     552ctxswitch-kos_fibre2$(EXEEXT):
     553        @${CXX}       ctxswitch/kos_fibre2.cpp -DBENCH_N=50000000  -I. -I/home/tdelisle/software/KOS/src/ -g -O2 -lfibre -lpthread -lrt
    530554
    531555ctxswitch-goroutine$(EXEEXT):
     
    539563
    540564mutex$(EXEEXT) :\
    541         mutex-function.run      \
    542         mutex-fetch_add.run     \
     565        loop.run                        \
     566        function.run            \
     567        fetch_add.run           \
    543568        mutex-pthread_lock.run  \
    544569        mutex-upp.run           \
     
    547572        mutex-cfa4.run          \
    548573        mutex-java_thread.run
    549 
    550 mutex-function$(EXEEXT):
    551         @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    552 
    553 mutex-fetch_add$(EXEEXT):
    554         @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    555574
    556575mutex-pthread_lock$(EXEEXT):
     
    682701
    683702compile-io$(EXEEXT):
    684         @${CC} -quiet -fsyntax-only -w ../tests/io.c                                    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     703        @${CC} -quiet -fsyntax-only -w ../tests/io1.c                           @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    685704
    686705compile-monitor$(EXEEXT):
    687         @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c            @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     706        @${CC} -quiet -fsyntax-only -w ../tests/concurrent/monitor.c    @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    688707
    689708compile-operators$(EXEEXT):
     
    694713
    695714compile-typeof$(EXEEXT):
    696         @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                                @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     715        @${CC} -quiet -fsyntax-only -w ../tests/typeof.c                        @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    697716
    698717# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • TabularUnified src/benchmark/function.c

    r0182bfa r28f3a19  
    44
    55void __attribute__((noinline)) do_call() {
    6         asm volatile ("");
     6        asm volatile("" ::: "memory");
    77}
    88
  • TabularUnified src/libcfa/Makefile.am

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

    r0182bfa r28f3a19  
    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
     99@BUILD_CONCURRENCY_TRUE@am__append_3 = concurrency/coroutine concurrency/thread concurrency/kernel concurrency/monitor concurrency/mutex
    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 assert.c \
    156         exception.c virtual.c concurrency/CtxSwitch-@MACHINE_TYPE@.S \
    157         concurrency/alarm.c concurrency/invoke.c \
    158         concurrency/preemption.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
    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)
     163@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-monitor.$(OBJEXT) \
     164@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_d_a-mutex.$(OBJEXT)
    164165am__objects_2 = libcfa_d_a-fstream.$(OBJEXT) \
    165166        libcfa_d_a-iostream.$(OBJEXT) libcfa_d_a-iterator.$(OBJEXT) \
     
    188189        containers/result.c containers/vector.c \
    189190        concurrency/coroutine.c concurrency/thread.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
     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
    194195@BUILD_CONCURRENCY_TRUE@am__objects_5 = concurrency/libcfa_a-coroutine.$(OBJEXT) \
    195196@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-thread.$(OBJEXT) \
    196197@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-kernel.$(OBJEXT) \
    197 @BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-monitor.$(OBJEXT)
     198@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-monitor.$(OBJEXT) \
     199@BUILD_CONCURRENCY_TRUE@        concurrency/libcfa_a-mutex.$(OBJEXT)
    198200am__objects_6 = libcfa_a-fstream.$(OBJEXT) libcfa_a-iostream.$(OBJEXT) \
    199201        libcfa_a-iterator.$(OBJEXT) libcfa_a-limits.$(OBJEXT) \
     
    264266        containers/result containers/vector concurrency/coroutine \
    265267        concurrency/thread concurrency/kernel concurrency/monitor \
    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
     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
    269271HEADERS = $(nobase_cfa_include_HEADERS)
    270272am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
     
    548550concurrency/libcfa_d_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
    549551        concurrency/$(DEPDIR)/$(am__dirstamp)
     552concurrency/libcfa_d_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
     553        concurrency/$(DEPDIR)/$(am__dirstamp)
    550554concurrency/CtxSwitch-@MACHINE_TYPE@.$(OBJEXT):  \
    551555        concurrency/$(am__dirstamp) \
     
    580584        concurrency/$(DEPDIR)/$(am__dirstamp)
    581585concurrency/libcfa_a-monitor.$(OBJEXT): concurrency/$(am__dirstamp) \
     586        concurrency/$(DEPDIR)/$(am__dirstamp)
     587concurrency/libcfa_a-mutex.$(OBJEXT): concurrency/$(am__dirstamp) \
    582588        concurrency/$(DEPDIR)/$(am__dirstamp)
    583589concurrency/libcfa_a-alarm.$(OBJEXT): concurrency/$(am__dirstamp) \
     
    635641@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-kernel.Po@am__quote@
    636642@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@
    637644@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-preemption.Po@am__quote@
    638645@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_a-thread.Po@am__quote@
     
    642649@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-kernel.Po@am__quote@
    643650@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@
    644652@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-preemption.Po@am__quote@
    645653@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/libcfa_d_a-thread.Po@am__quote@
     
    930938@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`
    931939
     940concurrency/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
     947concurrency/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
    932954libcfa_d_a-assert.o: assert.c
    933955@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
     
    12371259@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    12381260@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
     1262concurrency/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
     1269concurrency/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`
    12391275
    12401276libcfa_a-assert.o: assert.c
  • TabularUnified src/libcfa/bits/containers.h

    r0182bfa r28f3a19  
    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;
    185190        }
    186191#endif
     
    261266                __get( node ).prev = NULL;
    262267        }
     268
     269        forall(dtype T | sized(T))
     270        static inline bool ?!=?( __dllist(T) & this, zero_t zero ) {
     271                return this.head != 0;
     272        }
    263273        #undef next
    264274        #undef prev
  • TabularUnified src/libcfa/bits/locks.h

    r0182bfa r28f3a19  
    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
    2027
    2128// pause to prevent excess processor bus usage
     
    112119                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    113120        }
     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        }
    114165#endif
  • TabularUnified src/libcfa/concurrency/invoke.h

    r0182bfa r28f3a19  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 22:33:59 2018
    13 // Update Count     : 30
     12// Last Modified On : Sat May 19 08:23:21 2018
     13// Update Count     : 31
    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 
    2320#ifdef __cforall
    2421extern "C" {
     
    2825#ifndef _INVOKE_H_
    2926#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
    3045
    3146        #ifdef __cforall
  • TabularUnified src/libcfa/concurrency/kernel

    r0182bfa r28f3a19  
    2323extern "C" {
    2424#include <pthread.h>
     25#include <semaphore.h>
    2526}
    2627
     
    4344extern struct cluster * mainCluster;
    4445
    45 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };
     46enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
     47
     48typedef void (*__finish_callback_fptr_t)(void);
    4649
    4750//TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
    4851struct FinishAction {
    4952        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        /*/
    5079        thread_desc * thrd;
     80        thread_desc ** thrds;
     81        unsigned short thrd_count;
    5182        __spinlock_t * lock;
    5283        __spinlock_t ** locks;
    5384        unsigned short lock_count;
    54         thread_desc ** thrds;
    55         unsigned short thrd_count;
     85        __finish_callback_fptr_t callback;
     86        //*/
    5687};
    5788static inline void ?{}(FinishAction & this) {
     
    82113        pthread_t kernel_thread;
    83114
     115        // RunThread data
     116        // Action to do after a thread is ran
     117        struct FinishAction finish;
     118
     119        // Preemption data
     120        // Node which is added in the discrete event simulaiton
     121        struct alarm_node_t * preemption_alarm;
     122
     123        // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
     124        bool pending_preemption;
     125
     126        // Idle lock
     127        __bin_sem_t idleLock;
     128
    84129        // Termination
    85130        // Set to true to notify the processor should terminate
     
    89134        semaphore terminated;
    90135
    91         // RunThread data
    92         // Action to do after a thread is ran
    93         struct FinishAction finish;
    94 
    95         // Preemption data
    96         // Node which is added in the discrete event simulaiton
    97         struct alarm_node_t * preemption_alarm;
    98 
    99         // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible
    100         bool pending_preemption;
    101 
    102         // Idle lock
    103 
    104136        // Link lists fields
    105         struct {
     137        struct __dbg_node_proc {
    106138                struct processor * next;
    107139                struct processor * prev;
     
    150182
    151183        // Link lists fields
    152         struct {
     184        struct __dbg_node_cltr {
    153185                cluster * next;
    154186                cluster * prev;
  • TabularUnified src/libcfa/concurrency/kernel.c

    r0182bfa r28f3a19  
    1616//C Includes
    1717#include <stddef.h>
     18#include <errno.h>
     19#include <string.h>
    1820extern "C" {
    1921#include <stdio.h>
     
    4951thread_desc * mainThread;
    5052
    51 struct { __dllist_t(cluster    ) list; __spinlock_t lock; } global_clusters;
     53extern "C" {
     54struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
     55}
    5256
    5357//-----------------------------------------------------------------------------
     
    143147        runner.proc = &this;
    144148
     149        idleLock{};
     150
    145151        start( &this );
    146152}
    147153
    148154void ^?{}(processor & this) with( this ){
    149         if( ! do_terminate ) {
     155        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
    150156                __cfaabi_dbg_print_safe("Kernel : core %p signaling termination\n", &this);
    151                 terminate(&this);
    152                 verify(this.do_terminate);
    153                 verify( kernelTLS.this_processor != &this);
     157
     158                __atomic_store_n(&do_terminate, true, __ATOMIC_RELAXED);
     159                wake( &this );
     160
    154161                P( terminated );
    155162                verify( kernelTLS.this_processor != &this);
    156                 pthread_join( kernel_thread, NULL );
    157         }
     163        }
     164
     165        pthread_join( kernel_thread, NULL );
    158166}
    159167
     
    194202
    195203                thread_desc * readyThread = NULL;
    196                 for( unsigned int spin_count = 0; ! this->do_terminate; spin_count++ )
     204                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ )
    197205                {
    198206                        readyThread = nextThread( this->cltr );
     
    213221                        else
    214222                        {
    215                                 spin(this, &spin_count);
     223                                // spin(this, &spin_count);
     224                                halt(this);
    216225                        }
    217226                }
     
    257266// its final actions must be executed from the kernel
    258267void finishRunning(processor * this) with( this->finish ) {
    259         if( action_code == Release ) {
    260                 verify( ! kernelTLS.preemption_state.enabled );
     268        verify( ! kernelTLS.preemption_state.enabled );
     269        choose( action_code ) {
     270        case No_Action:
     271                break;
     272        case Release:
    261273                unlock( *lock );
    262         }
    263         else if( action_code == Schedule ) {
     274        case Schedule:
    264275                ScheduleThread( thrd );
    265         }
    266         else if( action_code == Release_Schedule ) {
    267                 verify( ! kernelTLS.preemption_state.enabled );
     276        case Release_Schedule:
    268277                unlock( *lock );
    269278                ScheduleThread( thrd );
    270         }
    271         else if( action_code == Release_Multi ) {
    272                 verify( ! kernelTLS.preemption_state.enabled );
     279        case Release_Multi:
    273280                for(int i = 0; i < lock_count; i++) {
    274281                        unlock( *locks[i] );
    275282                }
    276         }
    277         else if( action_code == Release_Multi_Schedule ) {
     283        case Release_Multi_Schedule:
    278284                for(int i = 0; i < lock_count; i++) {
    279285                        unlock( *locks[i] );
     
    282288                        ScheduleThread( thrds[i] );
    283289                }
    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
    292 void spin(processor * this, unsigned int * spin_count) {
    293         (*spin_count)++;
     290        case Callback:
     291                callback();
     292        default:
     293                abort("KERNEL ERROR: Unexpected action to run after thread");
     294        }
    294295}
    295296
     
    396397        with( *thrd->curr_cluster ) {
    397398                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
     399                bool was_empty = !(ready_queue != 0);
    398400                append( ready_queue, thrd );
    399401                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
    400414        }
    401415
     
    497511}
    498512
     513void 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
    499527// KERNEL ONLY
    500528void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
     
    518546        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    519547
    520         global_clusters.list{ __get };
    521         global_clusters.lock{};
     548        __cfa_dbg_global_clusters.list{ __get };
     549        __cfa_dbg_global_clusters.lock{};
    522550
    523551        // Initialize the main cluster
     
    600628        // When its coroutine terminates, it return control to the mainThread
    601629        // which is currently here
    602         mainProcessor->do_terminate = true;
     630        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    603631        returnToKernel();
     632        mainThread->self_cor.state = Halted;
    604633
    605634        // THE SYSTEM IS NOW COMPLETELY STOPPED
     
    617646        ^(mainThread){};
    618647
    619         ^(global_clusters.list){};
    620         ^(global_clusters.lock){};
     648        ^(__cfa_dbg_global_clusters.list){};
     649        ^(__cfa_dbg_global_clusters.lock){};
    621650
    622651        __cfaabi_dbg_print_safe("Kernel : Shutdown complete\n");
     
    627656//=============================================================================================
    628657
    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 // }
     658void 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}
    646681
    647682//=============================================================================================
     
    758793// Global Queues
    759794void doregister( cluster     & cltr ) {
    760         lock      ( global_clusters.lock __cfaabi_dbg_ctx2);
    761         push_front( global_clusters.list, cltr );
    762         unlock    ( global_clusters.lock );
     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 );
    763798}
    764799
    765800void unregister( cluster     & cltr ) {
    766         lock  ( global_clusters.lock __cfaabi_dbg_ctx2);
    767         remove( global_clusters.list, cltr );
    768         unlock( global_clusters.lock );
     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 );
    769804}
    770805
  • TabularUnified src/libcfa/concurrency/kernel_private.h

    r0182bfa r28f3a19  
    4848void BlockInternal(__spinlock_t * locks [], unsigned short count);
    4949void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
     50void BlockInternal(__finish_callback_fptr_t callback);
    5051void LeaveThread(__spinlock_t * lock, thread_desc * thrd);
    5152
     
    5657void runThread(processor * this, thread_desc * dst);
    5758void finishRunning(processor * this);
    58 void terminate(processor * this);
    59 void spin(processor * this, unsigned int * spin_count);
     59void halt(processor * this);
     60
     61static inline void wake_fast(processor * this) {
     62        __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
     63        post( this->idleLock );
     64}
     65
     66static inline void wake(processor * this) {
     67        disable_interrupts();
     68        wake_fast(this);
     69        enable_interrupts( __cfaabi_dbg_ctx );
     70}
    6071
    6172struct event_kernel_t {
     
    6576
    6677extern 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;
    7578
    7679struct __cfa_kernel_preemption_state_t {
  • TabularUnified src/libcfa/concurrency/monitor.c

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

    r0182bfa r28f3a19  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr  9 13:52:39 2018
    13 // Update Count     : 36
     12// Last Modified On : Tue Jun  5 17:35:49 2018
     13// Update Count     : 37
    1414//
    1515
     
    116116        // If there are still alarms pending, reset the timer
    117117        if( alarms->head ) {
    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);
     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);
    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
    163164                        static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     165                        #endif
    164166
    165167                        // Set enabled flag to false
     
    190192                        // Check if we need to prempt the thread because an interrupt was missed
    191193                        if( prev == 1 ) {
     194                                #if GCC_VERSION > 50000
    192195                                static_assert(__atomic_always_lock_free(sizeof(enabled), &enabled), "Must be lock-free");
     196                                #endif
    193197
    194198                                // Set enabled flag to true
     
    217221                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    218222                if( prev == 1 ) {
     223                        #if GCC_VERSION > 50000
    219224                        static_assert(__atomic_always_lock_free(sizeof(kernelTLS.preemption_state.enabled), &kernelTLS.preemption_state.enabled), "Must be lock-free");
     225                        #endif
    220226                        // Set enabled flag to true
    221227                        // should be atomic to avoid preemption in the middle of the operation.
     
    254260static void preempt( processor * this ) {
    255261        sigval_t value = { PREEMPT_NORMAL };
    256         pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    257 }
    258 
    259 // kill wrapper : signal a processor
    260 void terminate(processor * this) {
    261         this->do_terminate = true;
    262         sigval_t value = { PREEMPT_TERMINATE };
    263262        pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    264263}
     
    362361        choose(sfp->si_value.sival_int) {
    363362                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
    364                 case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate);
     363                case PREEMPT_TERMINATE: verify( __atomic_load_n( &kernelTLS.this_processor->do_terminate, __ATOMIC_SEQ_CST ) );
    365364                default:
    366365                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     
    376375
    377376        // 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
    379380        if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), NULL ) == -1 ) {
    380381                abort( "internal error, sigprocmask" );
     
    479480}
    480481
     482#ifdef __CFA_WITH_VERIFY__
     483bool __cfaabi_dbg_in_kernel() {
     484        return !kernelTLS.preemption_state.enabled;
     485}
     486#endif
     487
    481488// Local Variables: //
    482489// mode: c //
  • TabularUnified src/libcfa/fstream

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

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

    r0182bfa r28f3a19  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 28 13:08:24 2018
    13 // Update Count     : 152
     12// Last Modified On : Sat Jun  2 08:07:55 2018
     13// Update Count     : 153
    1414//
    1515
     
    5656// implement writable for intrinsic types
    5757
    58 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, _Bool );
     58forall( dtype ostype | ostream( ostype ) ) {
     59        ostype & ?|?( ostype &, _Bool );
    5960
    60 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, char );
    61 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, signed char );
    62 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned char );
     61        ostype & ?|?( ostype &, char );
     62        ostype & ?|?( ostype &, signed char );
     63        ostype & ?|?( ostype &, unsigned char );
    6364
    64 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, short int );
    65 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned short int );
    66 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, int );
    67 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned int );
    68 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long int );
    69 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long long int );
    70 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned long int );
    71 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, unsigned long long int );
     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 );
    7273
    73 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, float ); // FIX ME: should not be required
    74 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, double );
    75 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long double );
     74        ostype & ?|?( ostype &, float ); // FIX ME: should not be required
     75        ostype & ?|?( ostype &, double );
     76        ostype & ?|?( ostype &, long double );
    7677
    77 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, float _Complex );
    78 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, double _Complex );
    79 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, long double _Complex );
     78        ostype & ?|?( ostype &, float _Complex );
     79        ostype & ?|?( ostype &, double _Complex );
     80        ostype & ?|?( ostype &, long double _Complex );
    8081
    81 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char * );
    82 //forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char16_t * );
     82        ostype & ?|?( ostype &, const char * );
     83        // ostype & ?|?( ostype &, const char16_t * );
    8384#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    84 //forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const char32_t * );
     85        // ostype & ?|?( ostype &, const char32_t * );
    8586#endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    86 //forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const wchar_t * );
    87 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, const void * );
     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
    88100
    89101// tuples
    90102forall( dtype ostype, otype T, ttype Params | writeable( T, ostype ) | { ostype & ?|?( ostype &, Params ); } )
    91103ostype & ?|?( ostype & os, T arg, Params rest );
    92 
    93 // manipulators
    94 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype &, ostype & (*)( ostype & ) );
    95 forall( dtype ostype | ostream( ostype ) ) ostype & endl( ostype & );
    96 forall( dtype ostype | ostream( ostype ) ) ostype & sep( ostype & );
    97 forall( dtype ostype | ostream( ostype ) ) ostype & sepTuple( ostype & );
    98 forall( dtype ostype | ostream( ostype ) ) ostype & sepOn( ostype & );
    99 forall( dtype ostype | ostream( ostype ) ) ostype & sepOff( ostype & );
    100 forall( dtype ostype | ostream( ostype ) ) ostype & sepDisable( ostype & );
    101 forall( dtype ostype | ostream( ostype ) ) ostype & sepEnable( ostype & );
    102104
    103105// writes the range [begin, end) to the given stream
     
    124126}; // readable
    125127
    126 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, _Bool & );
     128forall( dtype istype | istream( istype ) ) {
     129        istype & ?|?( istype &, _Bool & );
    127130
    128 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, char & );
    129 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, signed char & );
    130 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned char & );
     131        istype & ?|?( istype &, char & );
     132        istype & ?|?( istype &, signed char & );
     133        istype & ?|?( istype &, unsigned char & );
    131134
    132 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, short int & );
    133 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned short int & );
    134 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, int & );
    135 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned int & );
    136 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long int & );
    137 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long long int & );
    138 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned long int & );
    139 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, unsigned long long int & );
     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 & );
    140143
    141 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, float & );
    142 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, double & );
    143 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long double & );
     144        istype & ?|?( istype &, float & );
     145        istype & ?|?( istype &, double & );
     146        istype & ?|?( istype &, long double & );
    144147
    145 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, float _Complex & );
    146 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, double _Complex & );
    147 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, long double _Complex & );
     148        istype & ?|?( istype &, float _Complex & );
     149        istype & ?|?( istype &, double _Complex & );
     150        istype & ?|?( istype &, long double _Complex & );
    148151
    149 // manipulators
    150 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, istype & (*)( istype & ) );
    151 forall( dtype istype | istream( istype ) ) istype & endl( istype & is );
     152        // manipulators
     153        istype & ?|?( istype &, istype & (*)( istype & ) );
     154        istype & endl( istype & is );
     155} // distribution
    152156
    153157struct _Istream_cstrUC { char * s; };
  • TabularUnified src/libcfa/iostream.c

    r0182bfa r28f3a19  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 28 13:08:25 2018
    13 // Update Count     : 469
     12// Last Modified On : Sat Jun  2 08:24:56 2018
     13// Update Count     : 471
    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 forall( dtype ostype | ostream( ostype ) )
    36 ostype & ?|?( ostype & os, char ch ) {
    37         fmt( os, "%c", ch );
    38         if ( ch == '\n' ) setNL( os, true );
    39         sepOff( os );
    40         return os;
    41 } // ?|?
    42 
    43 forall( dtype ostype | ostream( ostype ) )
    44 ostype & ?|?( ostype & os, signed char c ) {
    45         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    46         fmt( os, "%hhd", c );
    47         return os;
    48 } // ?|?
    49 
    50 forall( dtype ostype | ostream( ostype ) )
    51 ostype & ?|?( ostype & os, unsigned char c ) {
    52         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    53         fmt( os, "%hhu", c );
    54         return os;
    55 } // ?|?
    56 
    57 forall( dtype ostype | ostream( ostype ) )
    58 ostype & ?|?( ostype & os, short int si ) {
    59         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    60         fmt( os, "%hd", si );
    61         return os;
    62 } // ?|?
    63 
    64 forall( dtype ostype | ostream( ostype ) )
    65 ostype & ?|?( 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 
    71 forall( dtype ostype | ostream( ostype ) )
    72 ostype & ?|?( ostype & os, int i ) {
    73         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    74         fmt( os, "%d", i );
    75         return os;
    76 } // ?|?
    77 
    78 forall( dtype ostype | ostream( ostype ) )
    79 ostype & ?|?( ostype & os, unsigned int ui ) {
    80         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    81         fmt( os, "%u", ui );
    82         return os;
    83 } // ?|?
    84 
    85 forall( dtype ostype | ostream( ostype ) )
    86 ostype & ?|?( ostype & os, long int li ) {
    87         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    88         fmt( os, "%ld", li );
    89         return os;
    90 } // ?|?
    91 
    92 forall( dtype ostype | ostream( ostype ) )
    93 ostype & ?|?( 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 
    99 forall( dtype ostype | ostream( ostype ) )
    100 ostype & ?|?( 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 
    106 forall( dtype ostype | ostream( ostype ) )
    107 ostype & ?|?( 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 
    113 forall( dtype ostype | ostream( ostype ) )
    114 ostype & ?|?( ostype & os, float f ) {
    115         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    116         fmt( os, "%g", f );
    117         return os;
    118 } // ?|?
    119 
    120 forall( dtype ostype | ostream( ostype ) )
    121 ostype & ?|?( 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 
    127 forall( dtype ostype | ostream( ostype ) )
    128 ostype & ?|?( 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 
    134 forall( dtype ostype | ostream( ostype ) )
    135 ostype & ?|?( 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 
    141 forall( dtype ostype | ostream( ostype ) )
    142 ostype & ?|?( 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 
    148 forall( dtype ostype | ostream( ostype ) )
    149 ostype & ?|?( 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 
    155 forall( dtype ostype | ostream( ostype ) )
    156 ostype & ?|?( 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 ) {
     28forall( 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 );
     38                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//      } // ?|?
     182
     183// #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//      } // ?|?
     189// #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
     190
     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 ) {
    187228                sepOn( os );
    188         } else {
     229                return os;
     230        } // sepOn
     231
     232        ostype & sepOff( ostype & os ) {
    189233                sepOff( os );
    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 // } // ?|?
    201 
    202 // #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    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 // } // ?|?
    209 // #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    210 
    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 
    218 forall( dtype ostype | ostream( ostype ) )
    219 ostype & ?|?( ostype & os, const void * p ) {
    220         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
    221         fmt( os, "%p", p );
    222         return os;
    223 } // ?|?
     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
    224247
    225248
     
    234257} // ?|?
    235258
    236 
    237 // manipulators
    238 forall( dtype ostype | ostream( ostype ) )
    239 ostype & ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
    240         return manip( os );
    241 } // ?|?
    242 
    243 forall( dtype ostype | ostream( ostype ) )
    244 ostype & sep( ostype & os ) {
    245         os | sepGet( os );
    246         return os;
    247 } // sep
    248 
    249 forall( dtype ostype | ostream( ostype ) )
    250 ostype & sepTuple( ostype & os ) {
    251         os | sepGetTuple( os );
    252         return os;
    253 } // sepTuple
    254 
    255 forall( dtype ostype | ostream( ostype ) )
    256 ostype & 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 
    264 forall( dtype ostype | ostream( ostype ) )
    265 ostype & sepOn( ostype & os ) {
    266         sepOn( os );
    267         return os;
    268 } // sepOn
    269 
    270 forall( dtype ostype | ostream( ostype ) )
    271 ostype & sepOff( ostype & os ) {
    272         sepOff( os );
    273         return os;
    274 } // sepOff
    275 
    276 forall( dtype ostype | ostream( ostype ) )
    277 ostype & sepEnable( ostype & os ) {
    278         sepEnable( os );
    279         return os;
    280 } // sepEnable
    281 
    282 forall( dtype ostype | ostream( ostype ) )
    283 ostype & sepDisable( ostype & os ) {
    284         sepDisable( os );
    285         return os;
    286 } // sepDisable
    287 
    288259//---------------------------------------
    289260
     261// writes the range [begin, end) to the given stream
    290262forall( dtype ostype, otype elt_type | writeable( elt_type, ostype ), otype iterator_type | iterator( iterator_type, elt_type ) )
    291263void write( iterator_type begin, iterator_type end, ostype & os ) {
     
    302274//---------------------------------------
    303275
    304 forall( dtype istype | istream( istype ) )
    305 istype & ?|?( 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 
    317 forall( dtype istype | istream( istype ) )
    318 istype & ?|?( istype & is, char & c ) {
    319         fmt( is, "%c", &c );                                                            // must pass pointer through varg to fmt
    320         return is;
    321 } // ?|?
    322 
    323 forall( dtype istype | istream( istype ) )
    324 istype & ?|?( istype & is, signed char & sc ) {
    325         fmt( is, "%hhd", &sc );
    326         return is;
    327 } // ?|?
    328 
    329 forall( dtype istype | istream( istype ) )
    330 istype & ?|?( istype & is, unsigned char & usc ) {
    331         fmt( is, "%hhu", &usc );
    332         return is;
    333 } // ?|?
    334 
    335 forall( dtype istype | istream( istype ) )
    336 istype & ?|?( istype & is, short int & si ) {
    337         fmt( is, "%hd", &si );
    338         return is;
    339 } // ?|?
    340 
    341 forall( dtype istype | istream( istype ) )
    342 istype & ?|?( istype & is, unsigned short int & usi ) {
    343         fmt( is, "%hu", &usi );
    344         return is;
    345 } // ?|?
    346 
    347 forall( dtype istype | istream( istype ) )
    348 istype & ?|?( istype & is, int & i ) {
    349         fmt( is, "%d", &i );
    350         return is;
    351 } // ?|?
    352 
    353 forall( dtype istype | istream( istype ) )
    354 istype & ?|?( istype & is, unsigned int & ui ) {
    355         fmt( is, "%u", &ui );
    356         return is;
    357 } // ?|?
    358 
    359 forall( dtype istype | istream( istype ) )
    360 istype & ?|?( istype & is, long int & li ) {
    361         fmt( is, "%ld", &li );
    362         return is;
    363 } // ?|?
    364 
    365 forall( dtype istype | istream( istype ) )
    366 istype & ?|?( istype & is, unsigned long int & ulli ) {
    367         fmt( is, "%lu", &ulli );
    368         return is;
    369 } // ?|?
    370 
    371 forall( dtype istype | istream( istype ) )
    372 istype & ?|?( istype & is, long long int & lli ) {
    373         fmt( is, "%lld", &lli );
    374         return is;
    375 } // ?|?
    376 
    377 forall( dtype istype | istream( istype ) )
    378 istype & ?|?( istype & is, unsigned long long int & ulli ) {
    379         fmt( is, "%llu", &ulli );
    380         return is;
    381 } // ?|?
    382 
    383 
    384 forall( dtype istype | istream( istype ) )
    385 istype & ?|?( istype & is, float & f ) {
    386         fmt( is, "%f", &f );
    387         return is;
    388 } // ?|?
    389 
    390 forall( dtype istype | istream( istype ) )
    391 istype & ?|?( istype & is, double & d ) {
    392         fmt( is, "%lf", &d );
    393         return is;
    394 } // ?|?
    395 
    396 forall( dtype istype | istream( istype ) )
    397 istype & ?|?( istype & is, long double & ld ) {
    398         fmt( is, "%Lf", &ld );
    399         return is;
    400 } // ?|?
    401 
    402 
    403 forall( dtype istype | istream( istype ) )
    404 istype & ?|?( 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 
    411 forall( dtype istype | istream( istype ) )
    412 istype & ?|?( 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 
    419 forall( dtype istype | istream( istype ) )
    420 istype & ?|?( 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 
    427 forall( dtype istype | istream( istype ) )
    428 istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
    429         return manip( is );
    430 } // ?|?
    431 
    432 forall( dtype istype | istream( istype ) )
    433 istype & endl( istype & is ) {
    434         fmt( is, "%*[ \t\f\n\r\v]" );                                           // ignore whitespace
    435         return is;
    436 } // endl
     276forall( 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
    437393
    438394_Istream_cstrUC cstr( char * str ) { return (_Istream_cstrUC){ str }; }
  • TabularUnified src/libcfa/rational

    r0182bfa r28f3a19  
    1212// Created On       : Wed Apr  6 17:56:25 2016
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Wed Dec  6 23:12:53 2017
    15 // Update Count     : 97
     14// Last Modified On : Sat Jun  2 09:10:01 2018
     15// Update Count     : 105
    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 ) ) {
     49        struct Rational {
     50                RationalImpl numerator, denominator;                    // invariant: denominator > 0
     51        }; // Rational
    5252
    53 // constructors
     53        // constructors
    5454
    55 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    56 void ?{}( Rational(RationalImpl) & r );
     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 );
    5760
    58 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    59 void ?{}( Rational(RationalImpl) & r, RationalImpl n );
     61        // numerator/denominator getter
    6062
    61 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    62 void ?{}( Rational(RationalImpl) & r, RationalImpl n, RationalImpl d );
     63        RationalImpl numerator( Rational(RationalImpl) r );
     64        RationalImpl denominator( Rational(RationalImpl) r );
     65        [ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src );
    6366
    64 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    65 void ?{}( Rational(RationalImpl) & r, zero_t );
     67        // numerator/denominator setter
    6668
    67 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    68 void ?{}( Rational(RationalImpl) & r, one_t );
     69        RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n );
     70        RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d );
    6971
    70 // numerator/denominator getter
     72        // comparison
    7173
    72 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    73 RationalImpl numerator( Rational(RationalImpl) r );
     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 );
    7480
    75 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    76 RationalImpl denominator( Rational(RationalImpl) r );
     81        // arithmetic
    7782
    78 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    79 [ RationalImpl, RationalImpl ] ?=?( & [ RationalImpl, RationalImpl ] dest, Rational(RationalImpl) src );
     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 );
    8089
    81 // numerator/denominator setter
     90        // I/O
     91        forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
     92        istype & ?|?( istype &, Rational(RationalImpl) & );
    8293
    83 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    84 RationalImpl numerator( Rational(RationalImpl) r, RationalImpl n );
    85 
    86 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    87 RationalImpl denominator( Rational(RationalImpl) r, RationalImpl d );
    88 
    89 // comparison
    90 
    91 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    92 int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    93 
    94 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    95 int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    96 
    97 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    98 int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    99 
    100 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    101 int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    102 
    103 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    104 int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    105 
    106 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    107 int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    108 
    109 // arithmetic
    110 
    111 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    112 Rational(RationalImpl) +?( Rational(RationalImpl) r );
    113 
    114 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    115 Rational(RationalImpl) -?( Rational(RationalImpl) r );
    116 
    117 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    118 Rational(RationalImpl) ?+?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    119 
    120 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    121 Rational(RationalImpl) ?-?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    122 
    123 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    124 Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r );
    125 
    126 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    127 Rational(RationalImpl) ?/?( Rational(RationalImpl) l, Rational(RationalImpl) r );
     94        forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
     95        ostype & ?|?( ostype &, Rational(RationalImpl ) );
     96} // distribution
    12897
    12998// conversion
     
    133102Rational(RationalImpl) narrow( double f, RationalImpl md );
    134103
    135 // I/O
    136 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    137 forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    138 istype & ?|?( istype &, Rational(RationalImpl) & );
    139 
    140 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    141 forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
    142 ostype & ?|?( ostype &, Rational(RationalImpl ) );
    143 
    144104// Local Variables: //
    145105// mode: c //
  • TabularUnified src/libcfa/rational.c

    r0182bfa r28f3a19  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec  6 23:13:58 2017
    13 // Update Count     : 156
     12// Last Modified On : Sat Jun  2 09:24:33 2018
     13// Update Count     : 162
    1414//
    1515
     
    1818#include "stdlib"
    1919
    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
    24 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    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 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    36 static 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 
    48 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    49 void ?{}( Rational(RationalImpl) & r ) {
    50         r{ (RationalImpl){0}, (RationalImpl){1} };
    51 } // rational
    52 
    53 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    54 void ?{}( Rational(RationalImpl) & r, RationalImpl n ) {
    55         r{ n, (RationalImpl){1} };
    56 } // rational
    57 
    58 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    59 void ?{}( 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 
    68 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    69 RationalImpl numerator( Rational(RationalImpl) r ) {
    70         return r.numerator;
    71 } // numerator
    72 
    73 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    74 RationalImpl denominator( Rational(RationalImpl) r ) {
    75         return r.denominator;
    76 } // denominator
    77 
    78 forall( 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 
    85 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    86 RationalImpl 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 
    94 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    95 RationalImpl 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 
    106 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    107 int ?==?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    108         return l.numerator * r.denominator == l.denominator * r.numerator;
    109 } // ?==?
    110 
    111 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    112 int ?!=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    113         return ! ( l == r );
    114 } // ?!=?
    115 
    116 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    117 int ?<?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    118         return l.numerator * r.denominator < l.denominator * r.numerator;
    119 } // ?<?
    120 
    121 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    122 int ?<=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    123         return l.numerator * r.denominator <= l.denominator * r.numerator;
    124 } // ?<=?
    125 
    126 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    127 int ?>?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    128         return ! ( l <= r );
    129 } // ?>?
    130 
    131 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    132 int ?>=?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    133         return ! ( l < r );
    134 } // ?>=?
    135 
    136 
    137 // arithmetic
    138 
    139 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    140 Rational(RationalImpl) +?( Rational(RationalImpl) r ) {
    141         Rational(RationalImpl) t = { r.numerator, r.denominator };
    142         return t;
    143 } // +?
    144 
    145 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    146 Rational(RationalImpl) -?( Rational(RationalImpl) r ) {
    147         Rational(RationalImpl) t = { -r.numerator, r.denominator };
    148         return t;
    149 } // -?
    150 
    151 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    152 Rational(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 
    162 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    163 Rational(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 
    173 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    174 Rational(RationalImpl) ?*?( Rational(RationalImpl) l, Rational(RationalImpl) r ) {
    175         Rational(RationalImpl) t = { l.numerator * r.numerator, l.denominator * r.denominator };
    176         return t;
    177 } // ?*?
    178 
    179 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    180 Rational(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 
     20forall( 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
    189182
    190183// conversion
     
    195188} // widen
    196189
    197 // http://www.ics.uci.edu/~eppstein/numth/frap.c
    198190forall( otype RationalImpl | arithmetic( RationalImpl ) | { double convert( RationalImpl ); RationalImpl convert( double ); } )
    199191Rational(RationalImpl) narrow( double f, RationalImpl md ) {
     192        // http://www.ics.uci.edu/~eppstein/numth/frap.c
    200193        if ( md <= (RationalImpl){1} ) {                                        // maximum fractional digits too small?
    201194                return (Rational(RationalImpl)){ convert( f ), (RationalImpl){1}}; // truncate fraction
     
    224217} // narrow
    225218
    226 
    227 // I/O
    228 
    229 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    230 forall( dtype istype | istream( istype ) | { istype & ?|?( istype &, RationalImpl & ); } )
    231 istype & ?|?( 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 
    240 forall( otype RationalImpl | arithmetic( RationalImpl ) )
    241 forall( dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, RationalImpl ); } )
    242 ostype & ?|?( ostype & os, Rational(RationalImpl ) r ) {
    243         return os | r.numerator | '/' | r.denominator;
    244 } // ?|?
    245 
    246219// Local Variables: //
    247220// tab-width: 4 //
  • TabularUnified src/libcfa/stdhdr/assert.h

    r0182bfa r28f3a19  
    3333        #define verify(x) assert(x)
    3434        #define verifyf(x, ...) assertf(x, __VA_ARGS__)
     35        #define __CFA_WITH_VERIFY__
    3536#else
    3637        #define verify(x)
  • TabularUnified src/libcfa/stdlib

    r0182bfa r28f3a19  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 16 07:53:10 2018
    13 // Update Count     : 300
     12// Last Modified On : Sat Jun  2 08:46:35 2018
     13// Update Count     : 306
    1414//
    1515
    1616#pragma once
    1717
    18 #include <stdlib.h>                                                                             // strto*, *abs
     18#include <stdlib.h>                                                                             // allocation, strto*, *abs
     19extern "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"
    1924
    2025//---------------------------------------
     
    2732//---------------------------------------
    2833
    29 // C dynamic allocation
    3034static inline forall( dtype T | sized(T) ) {
     35        // C dynamic allocation
     36
    3137        T * malloc( void ) {
    3238                // printf( "* malloc\n" );
     
    5157        } // realloc
    5258
    53         extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void *
    5459        T * memalign( size_t align ) {
    5560                //printf( "X4\n" );
     
    5762        } // memalign
    5863
    59         extern "C" { void * aligned_alloc( size_t align, size_t size ); } // use default C routine for void *
    6064        T * aligned_alloc( size_t align ) {
    6165                //printf( "X5\n" );
     
    7074
    7175        // Cforall dynamic allocation
    72         extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void *
    7376
    7477        T * alloc( void ) {
     
    103106forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    104107
    105 static 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
    109 static 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 
    115 static 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
    119 static 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
    127 static 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
    131 extern "C" { void * memcpy( void * dest, const void * src, size_t size ); } // use default C routine for void *
    132 static 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
    138 static 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
    142 static 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
     108
     109static 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
     134static 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
     150static 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
    146163
    147164// allocation/deallocation and constructor/destructor, non-array types
     
    189206//---------------------------------------
    190207
    191 forall( otype E | { int ?<?( E, E ); } )
    192 E * bsearch( E key, const E * vals, size_t dim );
    193 
    194 forall( otype E | { int ?<?( E, E ); } )
    195 size_t bsearch( E key, const E * vals, size_t dim );
    196 
    197 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    198 E * bsearch( K key, const E * vals, size_t dim );
    199 
    200 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    201 size_t bsearch( K key, const E * vals, size_t dim );
    202 
    203 
    204 forall( otype E | { int ?<?( E, E ); } )
    205 E * bsearchl( E key, const E * vals, size_t dim );
    206 
    207 forall( otype E | { int ?<?( E, E ); } )
    208 size_t bsearchl( E key, const E * vals, size_t dim );
    209 
    210 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    211 E * bsearchl( K key, const E * vals, size_t dim );
    212 
    213 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    214 size_t bsearchl( K key, const E * vals, size_t dim );
    215 
    216 
    217 forall( otype E | { int ?<?( E, E ); } )
    218 E * bsearchu( E key, const E * vals, size_t dim );
    219 
    220 forall( otype E | { int ?<?( E, E ); } )
    221 size_t bsearchu( E key, const E * vals, size_t dim );
    222 
    223 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    224 E * bsearchu( K key, const E * vals, size_t dim );
    225 
    226 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    227 size_t bsearchu( K key, const E * vals, size_t dim );
    228 
    229 
    230 forall( otype E | { int ?<?( E, E ); } )
    231 void qsort( E * vals, size_t dim );
     208forall( 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
     219forall( 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
    232227
    233228//---------------------------------------
  • TabularUnified src/libcfa/stdlib.c

    r0182bfa r28f3a19  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan  3 08:29:29 2018
    13 // Update Count     : 444
     12// Last Modified On : Sat Jun  2 06:15:05 2018
     13// Update Count     : 448
    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 forall( otype E | { int ?<?( E, E ); } )
    141 size_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 
    146 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    147 E * 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 
    154 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    155 size_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 
    161 forall( otype E | { int ?<?( E, E ); } )
    162 size_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 
    175 forall( otype E | { int ?<?( E, E ); } )
    176 E * 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 
    181 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    182 size_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 
    195 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    196 E * 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 
    202 forall( otype E | { int ?<?( E, E ); } )
    203 size_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 
    216 forall( otype E | { int ?<?( E, E ); } )
    217 E * 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 
    222 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    223 size_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 
    236 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } )
    237 E * 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 
    243 forall( otype E | { int ?<?( E, E ); } )
    244 void 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
     132forall( 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
     191forall( 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
    250240
    251241//---------------------------------------
  • TabularUnified src/main.cc

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

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

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

    r0182bfa r28f3a19  
    11typedef.* size_t;
    22typedef.* ptrdiff_t;
     3typedef.* __int8_t;
     4typedef.* __int16_t;
     5typedef.* __int32_t;
     6typedef.* __int64_t;
     7typedef.* __uint8_t;
     8typedef.* __uint16_t;
     9typedef.* __uint32_t;
     10typedef.* __uint64_t;
    311typedef.* int8_t;
    412typedef.* int16_t;
  • TabularUnified src/prelude/prelude.cf

    r0182bfa r28f3a19  
    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 );
    461460zero_t                  ?=?( zero_t &, zero_t );
    462461one_t                   ?=?( one_t &, one_t );
  • TabularUnified src/prelude/sync-builtins.cf

    r0182bfa r28f3a19  
    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__)
    910__int128 __sync_fetch_and_add(volatile __int128 *, __int128,...);
    1011__int128 __sync_fetch_and_add_16(volatile __int128 *, __int128,...);
     12#endif
    1113
    1214char __sync_fetch_and_sub(volatile char *, char,...);
     
    1820long long int __sync_fetch_and_sub(volatile long long int *, long long int,...);
    1921long long int __sync_fetch_and_sub_8(volatile long long int *, long long int,...);
     22#if defined(__SIZEOF_INT128__)
    2023__int128 __sync_fetch_and_sub(volatile __int128 *, __int128,...);
    2124__int128 __sync_fetch_and_sub_16(volatile __int128 *, __int128,...);
     25#endif
    2226
    2327char __sync_fetch_and_or(volatile char *, char,...);
     
    2933long long int __sync_fetch_and_or(volatile long long int *, long long int,...);
    3034long long int __sync_fetch_and_or_8(volatile long long int *, long long int,...);
     35#if defined(__SIZEOF_INT128__)
    3136__int128 __sync_fetch_and_or(volatile __int128 *, __int128,...);
    3237__int128 __sync_fetch_and_or_16(volatile __int128 *, __int128,...);
     38#endif
    3339
    3440char __sync_fetch_and_and(volatile char *, char,...);
     
    4046long long int __sync_fetch_and_and(volatile long long int *, long long int,...);
    4147long long int __sync_fetch_and_and_8(volatile long long int *, long long int,...);
     48#if defined(__SIZEOF_INT128__)
    4249__int128 __sync_fetch_and_and(volatile __int128 *, __int128,...);
    4350__int128 __sync_fetch_and_and_16(volatile __int128 *, __int128,...);
     51#endif
    4452
    4553char __sync_fetch_and_xor(volatile char *, char,...);
     
    5159long long int __sync_fetch_and_xor(volatile long long int *, long long int,...);
    5260long long int __sync_fetch_and_xor_8(volatile long long int *, long long int,...);
     61#if defined(__SIZEOF_INT128__)
    5362__int128 __sync_fetch_and_xor(volatile __int128 *, __int128,...);
    5463__int128 __sync_fetch_and_xor_16(volatile __int128 *, __int128,...);
     64#endif
    5565
    5666char __sync_fetch_and_nand(volatile char *, char,...);
     
    6272long long int __sync_fetch_and_nand(volatile long long int *, long long int,...);
    6373long long int __sync_fetch_and_nand_8(volatile long long int *, long long int,...);
     74#if defined(__SIZEOF_INT128__)
    6475__int128 __sync_fetch_and_nand(volatile __int128 *, __int128,...);
    6576__int128 __sync_fetch_and_nand_16(volatile __int128 *, __int128,...);
     77#endif
    6678
    6779char __sync_add_and_fetch(volatile char *, char,...);
     
    7385long long int __sync_add_and_fetch(volatile long long int *, long long int,...);
    7486long long int __sync_add_and_fetch_8(volatile long long int *, long long int,...);
     87#if defined(__SIZEOF_INT128__)
    7588__int128 __sync_add_and_fetch(volatile __int128 *, __int128,...);
    7689__int128 __sync_add_and_fetch_16(volatile __int128 *, __int128,...);
     90#endif
    7791
    7892char __sync_sub_and_fetch(volatile char *, char,...);
     
    8498long long int __sync_sub_and_fetch(volatile long long int *, long long int,...);
    8599long long int __sync_sub_and_fetch_8(volatile long long int *, long long int,...);
     100#if defined(__SIZEOF_INT128__)
    86101__int128 __sync_sub_and_fetch(volatile __int128 *, __int128,...);
    87102__int128 __sync_sub_and_fetch_16(volatile __int128 *, __int128,...);
     103#endif
    88104
    89105char __sync_or_and_fetch(volatile char *, char,...);
     
    95111long long int __sync_or_and_fetch(volatile long long int *, long long int,...);
    96112long long int __sync_or_and_fetch_8(volatile long long int *, long long int,...);
     113#if defined(__SIZEOF_INT128__)
    97114__int128 __sync_or_and_fetch(volatile __int128 *, __int128,...);
    98115__int128 __sync_or_and_fetch_16(volatile __int128 *, __int128,...);
     116#endif
    99117
    100118char __sync_and_and_fetch(volatile char *, char,...);
     
    106124long long int __sync_and_and_fetch(volatile long long int *, long long int,...);
    107125long long int __sync_and_and_fetch_8(volatile long long int *, long long int,...);
     126#if defined(__SIZEOF_INT128__)
    108127__int128 __sync_and_and_fetch(volatile __int128 *, __int128,...);
    109128__int128 __sync_and_and_fetch_16(volatile __int128 *, __int128,...);
     129#endif
    110130
    111131char __sync_xor_and_fetch(volatile char *, char,...);
     
    117137long long int __sync_xor_and_fetch(volatile long long int *, long long int,...);
    118138long long int __sync_xor_and_fetch_8(volatile long long int *, long long int,...);
     139#if defined(__SIZEOF_INT128__)
    119140__int128 __sync_xor_and_fetch(volatile __int128 *, __int128,...);
    120141__int128 __sync_xor_and_fetch_16(volatile __int128 *, __int128,...);
     142#endif
    121143
    122144char __sync_nand_and_fetch(volatile char *, char,...);
     
    128150long long int __sync_nand_and_fetch(volatile long long int *, long long int,...);
    129151long long int __sync_nand_and_fetch_8(volatile long long int *, long long int,...);
     152#if defined(__SIZEOF_INT128__)
    130153__int128 __sync_nand_and_fetch(volatile __int128 *, __int128,...);
    131154__int128 __sync_nand_and_fetch_16(volatile __int128 *, __int128,...);
     155#endif
    132156
    133157_Bool __sync_bool_compare_and_swap(volatile char *, char, char,...);
     
    139163_Bool __sync_bool_compare_and_swap(volatile long long int *, long long int, long long int,...);
    140164_Bool __sync_bool_compare_and_swap_8(volatile long long int *, long long int, long long int,...);
     165#if defined(__SIZEOF_INT128__)
    141166_Bool __sync_bool_compare_and_swap(volatile __int128 *, __int128, __int128,...);
    142167_Bool __sync_bool_compare_and_swap_16(volatile __int128 *, __int128, __int128,...);
     168#endif
    143169
    144170char __sync_val_compare_and_swap(volatile char *, char, char,...);
     
    150176long long int __sync_val_compare_and_swap(volatile long long int *, long long int, long long int,...);
    151177long long int __sync_val_compare_and_swap_8(volatile long long int *, long long int, long long int,...);
     178#if defined(__SIZEOF_INT128__)
    152179__int128 __sync_val_compare_and_swap(volatile __int128 *, __int128, __int128,...);
    153180__int128 __sync_val_compare_and_swap_16(volatile __int128 *, __int128, __int128,...);
     181#endif
    154182
    155183char __sync_lock_test_and_set(volatile char *, char,...);
     
    161189long long int __sync_lock_test_and_set(volatile long long int *, long long int,...);
    162190long long int __sync_lock_test_and_set_8(volatile long long int *, long long int,...);
     191#if defined(__SIZEOF_INT128__)
    163192__int128 __sync_lock_test_and_set(volatile __int128 *, __int128,...);
    164193__int128 __sync_lock_test_and_set_16(volatile __int128 *, __int128,...);
     194#endif
    165195
    166196void __sync_lock_release(volatile char *,...);
     
    172202void __sync_lock_release(volatile long long int *,...);
    173203void __sync_lock_release_8(volatile long long int *,...);
     204#if defined(__SIZEOF_INT128__)
    174205void __sync_lock_release(volatile __int128 *,...);
    175206void __sync_lock_release_16(volatile __int128 *,...);
     207#endif
    176208
    177209void __sync_synchronize();
     
    185217_Bool __atomic_test_and_set(volatile int *, int);
    186218_Bool __atomic_test_and_set(volatile long long int *, int);
     219#if defined(__SIZEOF_INT128__)
    187220_Bool __atomic_test_and_set(volatile __int128 *, int);
     221#endif
     222
    188223void __atomic_clear(volatile _Bool *, int);
    189224void __atomic_clear(volatile char *, int);
     
    191226void __atomic_clear(volatile int *, int);
    192227void __atomic_clear(volatile long long int *, int);
     228#if defined(__SIZEOF_INT128__)
    193229void __atomic_clear(volatile __int128 *, int);
     230#endif
    194231
    195232char __atomic_exchange_n(volatile char *, volatile char *, int);
     
    205242long long int __atomic_exchange_8(volatile long long int *, long long int, int);
    206243void __atomic_exchange(volatile long long int *, volatile long long int *, volatile long long int *, int);
     244#if defined(__SIZEOF_INT128__)
    207245__int128 __atomic_exchange_n(volatile __int128 *, volatile __int128 *, int);
    208246__int128 __atomic_exchange_16(volatile __int128 *, __int128, int);
    209247void __atomic_exchange(volatile __int128 *, volatile __int128 *, volatile __int128 *, int);
    210 
     248#endif
     249
     250_Bool __atomic_load_n(const volatile _Bool *, int);
     251void __atomic_load(const volatile _Bool *, volatile _Bool *, int);
    211252char __atomic_load_n(const volatile char *, int);
    212253char __atomic_load_1(const volatile char *, int);
     
    221262long long int __atomic_load_8(const volatile long long int *, int);
    222263void __atomic_load(const volatile long long int *, volatile long long int *, int);
     264#if defined(__SIZEOF_INT128__)
    223265__int128 __atomic_load_n(const volatile __int128 *, int);
    224266__int128 __atomic_load_16(const volatile __int128 *, int);
    225267void __atomic_load(const volatile __int128 *, volatile __int128 *, int);
     268#endif
    226269
    227270_Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int);
     
    237280_Bool __atomic_compare_exchange_8(volatile long long int *, long long int *, long long int, _Bool, int, int);
    238281_Bool __atomic_compare_exchange  (volatile long long int *, long long int *, long long int *, _Bool, int, int);
     282#if defined(__SIZEOF_INT128__)
    239283_Bool __atomic_compare_exchange_n (volatile __int128 *, __int128 *, __int128, _Bool, int, int);
    240284_Bool __atomic_compare_exchange_16(volatile __int128 *, __int128 *, __int128, _Bool, int, int);
    241285_Bool __atomic_compare_exchange   (volatile __int128 *, __int128 *, __int128 *, _Bool, int, int);
     286#endif
    242287
    243288void __atomic_store_n(volatile _Bool *, _Bool, int);
    244 void __atomic_store_1(volatile _Bool *, _Bool, int);
    245289void __atomic_store(volatile _Bool *, _Bool *, int);
    246290void __atomic_store_n(volatile char *, char, int);
     
    256300void __atomic_store_8(volatile long long int *, long long int, int);
    257301void __atomic_store(volatile long long int *, long long int *, int);
     302#if defined(__SIZEOF_INT128__)
    258303void __atomic_store_n(volatile __int128 *, __int128, int);
    259304void __atomic_store_16(volatile __int128 *, __int128, int);
    260305void __atomic_store(volatile __int128 *, __int128 *, int);
     306#endif
    261307
    262308char __atomic_add_fetch  (volatile char *, char, int);
     
    268314long long int __atomic_add_fetch  (volatile long long int *, long long int, int);
    269315long long int __atomic_add_fetch_8(volatile long long int *, long long int, int);
     316#if defined(__SIZEOF_INT128__)
    270317__int128 __atomic_add_fetch   (volatile __int128 *, __int128, int);
    271318__int128 __atomic_add_fetch_16(volatile __int128 *, __int128, int);
     319#endif
    272320
    273321char __atomic_sub_fetch  (volatile char *, char, int);
     
    279327long long int __atomic_sub_fetch  (volatile long long int *, long long int, int);
    280328long long int __atomic_sub_fetch_8(volatile long long int *, long long int, int);
     329#if defined(__SIZEOF_INT128__)
    281330__int128 __atomic_sub_fetch   (volatile __int128 *, __int128, int);
    282331__int128 __atomic_sub_fetch_16(volatile __int128 *, __int128, int);
     332#endif
    283333
    284334char __atomic_and_fetch  (volatile char *, char, int);
     
    290340long long int __atomic_and_fetch  (volatile long long int *, long long int, int);
    291341long long int __atomic_and_fetch_8(volatile long long int *, long long int, int);
     342#if defined(__SIZEOF_INT128__)
    292343__int128 __atomic_and_fetch   (volatile __int128 *, __int128, int);
    293344__int128 __atomic_and_fetch_16(volatile __int128 *, __int128, int);
     345#endif
    294346
    295347char __atomic_nand_fetch  (volatile char *, char, int);
     
    301353long long int __atomic_nand_fetch  (volatile long long int *, long long int, int);
    302354long long int __atomic_nand_fetch_8(volatile long long int *, long long int, int);
     355#if defined(__SIZEOF_INT128__)
    303356__int128 __atomic_nand_fetch   (volatile __int128 *, __int128, int);
    304357__int128 __atomic_nand_fetch_16(volatile __int128 *, __int128, int);
     358#endif
    305359
    306360char __atomic_xor_fetch  (volatile char *, char, int);
     
    312366long long int __atomic_xor_fetch  (volatile long long int *, long long int, int);
    313367long long int __atomic_xor_fetch_8(volatile long long int *, long long int, int);
     368#if defined(__SIZEOF_INT128__)
    314369__int128 __atomic_xor_fetch   (volatile __int128 *, __int128, int);
    315370__int128 __atomic_xor_fetch_16(volatile __int128 *, __int128, int);
     371#endif
    316372
    317373char __atomic_or_fetch  (volatile char *, char, int);
     
    323379long long int __atomic_or_fetch  (volatile long long int *, long long int, int);
    324380long long int __atomic_or_fetch_8(volatile long long int *, long long int, int);
     381#if defined(__SIZEOF_INT128__)
    325382__int128 __atomic_or_fetch   (volatile __int128 *, __int128, int);
    326383__int128 __atomic_or_fetch_16(volatile __int128 *, __int128, int);
     384#endif
    327385
    328386char __atomic_fetch_add  (volatile char *, char, int);
     
    334392long long int __atomic_fetch_add  (volatile long long int *, long long int, int);
    335393long long int __atomic_fetch_add_8(volatile long long int *, long long int, int);
     394#if defined(__SIZEOF_INT128__)
    336395__int128 __atomic_fetch_add   (volatile __int128 *, __int128, int);
    337396__int128 __atomic_fetch_add_16(volatile __int128 *, __int128, int);
     397#endif
    338398
    339399char __atomic_fetch_sub  (volatile char *, char, int);
     
    345405long long int __atomic_fetch_sub  (volatile long long int *, long long int, int);
    346406long long int __atomic_fetch_sub_8(volatile long long int *, long long int, int);
     407#if defined(__SIZEOF_INT128__)
    347408__int128 __atomic_fetch_sub   (volatile __int128 *, __int128, int);
    348409__int128 __atomic_fetch_sub_16(volatile __int128 *, __int128, int);
     410#endif
    349411
    350412char __atomic_fetch_and  (volatile char *, char, int);
     
    356418long long int __atomic_fetch_and  (volatile long long int *, long long int, int);
    357419long long int __atomic_fetch_and_8(volatile long long int *, long long int, int);
     420#if defined(__SIZEOF_INT128__)
    358421__int128 __atomic_fetch_and   (volatile __int128 *, __int128, int);
    359422__int128 __atomic_fetch_and_16(volatile __int128 *, __int128, int);
     423#endif
    360424
    361425char __atomic_fetch_nand  (volatile char *, char, int);
     
    367431long long int __atomic_fetch_nand  (volatile long long int *, long long int, int);
    368432long long int __atomic_fetch_nand_8(volatile long long int *, long long int, int);
     433#if defined(__SIZEOF_INT128__)
    369434__int128 __atomic_fetch_nand   (volatile __int128 *, __int128, int);
    370435__int128 __atomic_fetch_nand_16(volatile __int128 *, __int128, int);
     436#endif
    371437
    372438char __atomic_fetch_xor  (volatile char *, char, int);
     
    378444long long int __atomic_fetch_xor  (volatile long long int *, long long int, int);
    379445long long int __atomic_fetch_xor_8(volatile long long int *, long long int, int);
     446#if defined(__SIZEOF_INT128__)
    380447__int128 __atomic_fetch_xor   (volatile __int128 *, __int128, int);
    381448__int128 __atomic_fetch_xor_16(volatile __int128 *, __int128, int);
     449#endif
    382450
    383451char __atomic_fetch_or  (volatile char *, char, int);
     
    389457long long int __atomic_fetch_or  (volatile long long int *, long long int, int);
    390458long long int __atomic_fetch_or_8(volatile long long int *, long long int, int);
     459#if defined(__SIZEOF_INT128__)
    391460__int128 __atomic_fetch_or   (volatile __int128 *, __int128, int);
    392461__int128 __atomic_fetch_or_16(volatile __int128 *, __int128, int);
     462#endif
    393463
    394464_Bool __atomic_always_lock_free(unsigned long, const volatile void *);
  • TabularUnified src/tests/.gitignore

    r0182bfa r28f3a19  
    11.out/
    22.err/
     3.type
  • TabularUnified src/tests/Makefile.am

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

    r0182bfa r28f3a19  
    309309# applies to both programs
    310310DEBUG_FLAGS =
    311 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ \
     311BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -I. \
    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
    771 literals : literals.c @CFA_BINDIR@/@CFA_NAME@
    772         ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    773 
    774771sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@
    775772        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • TabularUnified src/tests/builtins/sync.c

    r0182bfa r28f3a19  
    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__)
    1011        volatile __int128 * vp16 = 0; __int128 * rp16 = 0; __int128 v16 = 0;
     12        #endif
    1113
    1214        { char ret; ret = __sync_fetch_and_add(vp1, v1); }
     
    1820        { long long int ret; ret = __sync_fetch_and_add(vp8, v8); }
    1921        { long long int ret; ret = __sync_fetch_and_add_8(vp8, v8); }
     22        #if defined(__SIZEOF_INT128__)
    2023        { __int128 ret; ret = __sync_fetch_and_add(vp16, v16); }
    2124        { __int128 ret; ret = __sync_fetch_and_add_16(vp16, v16); }
     25        #endif
    2226
    2327        { char ret; ret = __sync_fetch_and_sub(vp1, v1); }
     
    2933        { long long int ret; ret = __sync_fetch_and_sub(vp8, v8); }
    3034        { long long int ret; ret = __sync_fetch_and_sub_8(vp8, v8); }
     35        #if defined(__SIZEOF_INT128__)
    3136        { __int128 ret; ret = __sync_fetch_and_sub(vp16, v16); }
    3237        { __int128 ret; ret = __sync_fetch_and_sub_16(vp16, v16); }
     38        #endif
    3339
    3440        { char ret; ret = __sync_fetch_and_or(vp1, v1); }
     
    4046        { long long int ret; ret = __sync_fetch_and_or(vp8, v8); }
    4147        { long long int ret; ret = __sync_fetch_and_or_8(vp8, v8); }
     48        #if defined(__SIZEOF_INT128__)
    4249        { __int128 ret; ret = __sync_fetch_and_or(vp16, v16); }
    4350        { __int128 ret; ret = __sync_fetch_and_or_16(vp16, v16); }
     51        #endif
    4452
    4553        { char ret; ret = __sync_fetch_and_and(vp1, v1); }
     
    5159        { long long int ret; ret = __sync_fetch_and_and(vp8, v8); }
    5260        { long long int ret; ret = __sync_fetch_and_and_8(vp8, v8); }
     61        #if defined(__SIZEOF_INT128__)
    5362        { __int128 ret; ret = __sync_fetch_and_and(vp16, v16); }
    5463        { __int128 ret; ret = __sync_fetch_and_and_16(vp16, v16); }
     64        #endif
    5565
    5666        { char ret; ret = __sync_fetch_and_xor(vp1, v1); }
     
    6272        { long long int ret; ret = __sync_fetch_and_xor(vp8, v8); }
    6373        { long long int ret; ret = __sync_fetch_and_xor_8(vp8, v8); }
     74        #if defined(__SIZEOF_INT128__)
    6475        { __int128 ret; ret = __sync_fetch_and_xor(vp16, v16); }
    6576        { __int128 ret; ret = __sync_fetch_and_xor_16(vp16, v16); }
     77        #endif
    6678
    6779        { char ret; ret = __sync_fetch_and_nand(vp1, v1); }
     
    7385        { long long int ret; ret = __sync_fetch_and_nand(vp8, v8); }
    7486        { long long int ret; ret = __sync_fetch_and_nand_8(vp8, v8); }
     87        #if defined(__SIZEOF_INT128__)
    7588        { __int128 ret; ret = __sync_fetch_and_nand(vp16, v16); }
    7689        { __int128 ret; ret = __sync_fetch_and_nand_16(vp16, v16); }
     90        #endif
    7791
    7892        { char ret; ret = __sync_add_and_fetch(vp1, v1); }
     
    8498        { long long int ret; ret = __sync_add_and_fetch(vp8, v8); }
    8599        { long long int ret; ret = __sync_add_and_fetch_8(vp8, v8); }
     100        #if defined(__SIZEOF_INT128__)
    86101        { __int128 ret; ret = __sync_add_and_fetch(vp16, v16); }
    87102        { __int128 ret; ret = __sync_add_and_fetch_16(vp16, v16); }
     103        #endif
    88104
    89105        { char ret; ret = __sync_sub_and_fetch(vp1, v1); }
     
    95111        { long long int ret; ret = __sync_sub_and_fetch(vp8, v8); }
    96112        { long long int ret; ret = __sync_sub_and_fetch_8(vp8, v8); }
     113        #if defined(__SIZEOF_INT128__)
    97114        { __int128 ret; ret = __sync_sub_and_fetch(vp16, v16); }
    98115        { __int128 ret; ret = __sync_sub_and_fetch_16(vp16, v16); }
     116        #endif
    99117
    100118        { char ret; ret = __sync_or_and_fetch(vp1, v1); }
     
    106124        { long long int ret; ret = __sync_or_and_fetch(vp8, v8); }
    107125        { long long int ret; ret = __sync_or_and_fetch_8(vp8, v8); }
     126        #if defined(__SIZEOF_INT128__)
    108127        { __int128 ret; ret = __sync_or_and_fetch(vp16, v16); }
    109128        { __int128 ret; ret = __sync_or_and_fetch_16(vp16, v16); }
     129        #endif
    110130
    111131        { char ret; ret = __sync_and_and_fetch(vp1, v1); }
     
    117137        { long long int ret; ret = __sync_and_and_fetch(vp8, v8); }
    118138        { long long int ret; ret = __sync_and_and_fetch_8(vp8, v8); }
     139        #if defined(__SIZEOF_INT128__)
    119140        { __int128 ret; ret = __sync_and_and_fetch(vp16, v16); }
    120141        { __int128 ret; ret = __sync_and_and_fetch_16(vp16, v16); }
     142        #endif
    121143
    122144        { char ret; ret = __sync_xor_and_fetch(vp1, v1); }
     
    128150        { long long int ret; ret = __sync_xor_and_fetch(vp8, v8); }
    129151        { long long int ret; ret = __sync_xor_and_fetch_8(vp8, v8); }
     152        #if defined(__SIZEOF_INT128__)
    130153        { __int128 ret; ret = __sync_xor_and_fetch(vp16, v16); }
    131154        { __int128 ret; ret = __sync_xor_and_fetch_16(vp16, v16); }
     155        #endif
    132156
    133157        { char ret; ret = __sync_nand_and_fetch(vp1, v1); }
     
    139163        { long long int ret; ret = __sync_nand_and_fetch(vp8, v8); }
    140164        { long long int ret; ret = __sync_nand_and_fetch_8(vp8, v8); }
     165        #if defined(__SIZEOF_INT128__)
    141166        { __int128 ret; ret = __sync_nand_and_fetch(vp16, v16); }
    142167        { __int128 ret; ret = __sync_nand_and_fetch_16(vp16, v16); }
     168        #endif
    143169
    144170        { _Bool ret; ret = __sync_bool_compare_and_swap(vp1, v1, v1); }
     
    150176        { _Bool ret; ret = __sync_bool_compare_and_swap(vp8, v8, v8); }
    151177        { _Bool ret; ret = __sync_bool_compare_and_swap_8(vp8, v8, v8); }
     178        #if defined(__SIZEOF_INT128__)
    152179        { _Bool ret; ret = __sync_bool_compare_and_swap(vp16, v16, v16); }
    153180        { _Bool ret; ret = __sync_bool_compare_and_swap_16(vp16, v16,v16); }
     181        #endif
    154182
    155183        { char ret; ret = __sync_val_compare_and_swap(vp1, v1, v1); }
     
    161189        { long long int ret; ret = __sync_val_compare_and_swap(vp8, v8, v8); }
    162190        { long long int ret; ret = __sync_val_compare_and_swap_8(vp8, v8, v8); }
     191        #if defined(__SIZEOF_INT128__)
    163192        { __int128 ret; ret = __sync_val_compare_and_swap(vp16, v16, v16); }
    164193        { __int128 ret; ret = __sync_val_compare_and_swap_16(vp16, v16,v16); }
     194        #endif
    165195
    166196        { char ret; ret = __sync_lock_test_and_set(vp1, v1); }
     
    172202        { long long int ret; ret = __sync_lock_test_and_set(vp8, v8); }
    173203        { long long int ret; ret = __sync_lock_test_and_set_8(vp8, v8); }
     204        #if defined(__SIZEOF_INT128__)
    174205        { __int128 ret; ret = __sync_lock_test_and_set(vp16, v16); }
    175206        { __int128 ret; ret = __sync_lock_test_and_set_16(vp16, v16); }
     207        #endif
    176208
    177209        { __sync_lock_release(vp1); }
     
    183215        { __sync_lock_release(vp8); }
    184216        { __sync_lock_release_8(vp8); }
     217        #if defined(__SIZEOF_INT128__)
    185218        { __sync_lock_release(vp16); }
    186219        { __sync_lock_release_16(vp16); }
     220        #endif
    187221
    188222        { __sync_synchronize(); }
     
    208242        { long long int ret; ret = __atomic_exchange_8(vp8, v8, __ATOMIC_SEQ_CST); }
    209243        { long long int ret; __atomic_exchange(vp8, &v8, &ret, __ATOMIC_SEQ_CST); }
     244        #if defined(__SIZEOF_INT128__)
    210245        { __int128 ret; ret = __atomic_exchange_n(vp16, &v16, __ATOMIC_SEQ_CST); }
    211246        { __int128 ret; ret = __atomic_exchange_16(vp16, v16, __ATOMIC_SEQ_CST); }
    212247        { __int128 ret; __atomic_exchange(vp16, &v16, &ret, __ATOMIC_SEQ_CST); }
     248        #endif
    213249
    214250        { char ret; ret = __atomic_load_n(vp1, __ATOMIC_SEQ_CST); }
     
    224260        { long long int ret; ret = __atomic_load_8(vp8, __ATOMIC_SEQ_CST); }
    225261        { long long int ret; __atomic_load(vp8, &ret, __ATOMIC_SEQ_CST); }
     262        #if defined(__SIZEOF_INT128__)
    226263        { __int128 ret; ret = __atomic_load_n(vp16, __ATOMIC_SEQ_CST); }
    227264        { __int128 ret; ret = __atomic_load_16(vp16, __ATOMIC_SEQ_CST); }
    228265        { __int128 ret; __atomic_load(vp16, &ret, __ATOMIC_SEQ_CST); }
     266        #endif
    229267
    230268        { _Bool ret; ret = __atomic_compare_exchange_n(vp1, rp1, v1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
     
    240278        { _Bool ret; ret = __atomic_compare_exchange_8(vp8, rp8, v8, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    241279        { _Bool ret; ret = __atomic_compare_exchange(vp8, rp8, &v8, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
     280        #if defined(__SIZEOF_INT128__)
    242281        { _Bool ret; ret = __atomic_compare_exchange_n(vp16, rp16, v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    243282        { _Bool ret; ret = __atomic_compare_exchange_16(vp16, rp16, v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
    244283        { _Bool ret; ret = __atomic_compare_exchange(vp16, rp16, &v16, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); }
     284        #endif
    245285
    246286        { __atomic_store_n(vp1, v1, __ATOMIC_SEQ_CST); }
     
    256296        { __atomic_store_8(vp8, v8, __ATOMIC_SEQ_CST); }
    257297        { __atomic_store(vp8, &v8, __ATOMIC_SEQ_CST); }
     298        #if defined(__SIZEOF_INT128__)
    258299        { __atomic_store_n(vp16, v16, __ATOMIC_SEQ_CST); }
    259300        { __atomic_store_16(vp16, v16, __ATOMIC_SEQ_CST); }
    260301        { __atomic_store(vp16, &v16, __ATOMIC_SEQ_CST); }
     302        #endif
    261303
    262304        { char ret; ret = __atomic_add_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    268310        { long long int ret; ret = __atomic_add_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    269311        { long long int ret; ret = __atomic_add_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     312        #if defined(__SIZEOF_INT128__)
    270313        { __int128 ret; ret = __atomic_add_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    271314        { __int128 ret; ret = __atomic_add_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     315        #endif
    272316
    273317        { char ret; ret = __atomic_sub_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    279323        { long long int ret; ret = __atomic_sub_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    280324        { long long int ret; ret = __atomic_sub_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     325        #if defined(__SIZEOF_INT128__)
    281326        { __int128 ret; ret = __atomic_sub_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    282327        { __int128 ret; ret = __atomic_sub_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     328        #endif
    283329
    284330        { char ret; ret = __atomic_and_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    290336        { long long int ret; ret = __atomic_and_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    291337        { long long int ret; ret = __atomic_and_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     338        #if defined(__SIZEOF_INT128__)
    292339        { __int128 ret; ret = __atomic_and_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    293340        { __int128 ret; ret = __atomic_and_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     341        #endif
    294342
    295343        { char ret; ret = __atomic_nand_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    301349        { long long int ret; ret = __atomic_nand_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    302350        { long long int ret; ret = __atomic_nand_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     351        #if defined(__SIZEOF_INT128__)
    303352        { __int128 ret; ret = __atomic_nand_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    304353        { __int128 ret; ret = __atomic_nand_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     354        #endif
    305355
    306356        { char ret; ret = __atomic_xor_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    312362        { long long int ret; ret = __atomic_xor_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    313363        { long long int ret; ret = __atomic_xor_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     364        #if defined(__SIZEOF_INT128__)
    314365        { __int128 ret; ret = __atomic_xor_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    315366        { __int128 ret; ret = __atomic_xor_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     367        #endif
    316368
    317369        { char ret; ret = __atomic_or_fetch(vp1, v1, __ATOMIC_SEQ_CST); }
     
    323375        { long long int ret; ret = __atomic_or_fetch(vp8, v8, __ATOMIC_SEQ_CST); }
    324376        { long long int ret; ret = __atomic_or_fetch_8(vp8, v8, __ATOMIC_SEQ_CST); }
     377        #if defined(__SIZEOF_INT128__)
    325378        { __int128 ret; ret = __atomic_or_fetch(vp16, v16, __ATOMIC_SEQ_CST); }
    326379        { __int128 ret; ret = __atomic_or_fetch_16(vp16, v16, __ATOMIC_SEQ_CST); }
     380        #endif
    327381
    328382        { char ret; ret = __atomic_fetch_add(vp1, v1, __ATOMIC_SEQ_CST); }
     
    334388        { long long int ret; ret = __atomic_fetch_add(vp8, v8, __ATOMIC_SEQ_CST); }
    335389        { long long int ret; ret = __atomic_fetch_add_8(vp8, v8, __ATOMIC_SEQ_CST); }
     390        #if defined(__SIZEOF_INT128__)
    336391        { __int128 ret; ret = __atomic_fetch_add(vp16, v16, __ATOMIC_SEQ_CST); }
    337392        { __int128 ret; ret = __atomic_fetch_add_16(vp16, v16, __ATOMIC_SEQ_CST); }
     393        #endif
    338394
    339395        { char ret; ret = __atomic_fetch_sub(vp1, v1, __ATOMIC_SEQ_CST); }
     
    345401        { long long int ret; ret = __atomic_fetch_sub(vp8, v8, __ATOMIC_SEQ_CST); }
    346402        { long long int ret; ret = __atomic_fetch_sub_8(vp8, v8, __ATOMIC_SEQ_CST); }
     403        #if defined(__SIZEOF_INT128__)
    347404        { __int128 ret; ret = __atomic_fetch_sub(vp16, v16, __ATOMIC_SEQ_CST); }
    348405        { __int128 ret; ret = __atomic_fetch_sub_16(vp16, v16, __ATOMIC_SEQ_CST); }
     406        #endif
    349407
    350408        { char ret; ret = __atomic_fetch_and(vp1, v1, __ATOMIC_SEQ_CST); }
     
    356414        { long long int ret; ret = __atomic_fetch_and(vp8, v8, __ATOMIC_SEQ_CST); }
    357415        { long long int ret; ret = __atomic_fetch_and_8(vp8, v8, __ATOMIC_SEQ_CST); }
     416        #if defined(__SIZEOF_INT128__)
    358417        { __int128 ret; ret = __atomic_fetch_and(vp16, v16, __ATOMIC_SEQ_CST); }
    359418        { __int128 ret; ret = __atomic_fetch_and_16(vp16, v16, __ATOMIC_SEQ_CST); }
     419        #endif
    360420
    361421        { char ret; ret = __atomic_fetch_nand(vp1, v1, __ATOMIC_SEQ_CST); }
     
    367427        { long long int ret; ret = __atomic_fetch_nand(vp8, v8, __ATOMIC_SEQ_CST); }
    368428        { long long int ret; ret = __atomic_fetch_nand_8(vp8, v8, __ATOMIC_SEQ_CST); }
     429        #if defined(__SIZEOF_INT128__)
    369430        { __int128 ret; ret = __atomic_fetch_nand(vp16, v16, __ATOMIC_SEQ_CST); }
    370431        { __int128 ret; ret = __atomic_fetch_nand_16(vp16, v16, __ATOMIC_SEQ_CST); }
     432        #endif
    371433
    372434        { char ret; ret = __atomic_fetch_xor(vp1, v1, __ATOMIC_SEQ_CST); }
     
    378440        { long long int ret; ret = __atomic_fetch_xor(vp8, v8, __ATOMIC_SEQ_CST); }
    379441        { long long int ret; ret = __atomic_fetch_xor_8(vp8, v8, __ATOMIC_SEQ_CST); }
     442        #if defined(__SIZEOF_INT128__)
    380443        { __int128 ret; ret = __atomic_fetch_xor(vp16, v16, __ATOMIC_SEQ_CST); }
    381444        { __int128 ret; ret = __atomic_fetch_xor_16(vp16, v16, __ATOMIC_SEQ_CST); }
     445        #endif
    382446
    383447        { char ret; ret = __atomic_fetch_or(vp1, v1, __ATOMIC_SEQ_CST); }
     
    389453        { long long int ret; ret = __atomic_fetch_or(vp8, v8, __ATOMIC_SEQ_CST); }
    390454        { long long int ret; ret = __atomic_fetch_or_8(vp8, v8, __ATOMIC_SEQ_CST); }
     455        #if defined(__SIZEOF_INT128__)
    391456        { __int128 ret; ret = __atomic_fetch_or(vp16, v16, __ATOMIC_SEQ_CST); }
    392457        { __int128 ret; ret = __atomic_fetch_or_16(vp16, v16, __ATOMIC_SEQ_CST); }
     458        #endif
    393459
    394460        { _Bool ret; ret = __atomic_always_lock_free(sizeof(int), vp4); }
  • TabularUnified src/tests/concurrent/coroutineYield.c

    r0182bfa r28f3a19  
    44#include <thread>
    55#include <time>
     6
     7#define __kick_rate 150000ul
     8#include "long_tests.h"
    69
    710#ifndef PREEMPTION_RATE
     
    1316}
    1417
    15 #ifdef LONG_TEST
     18#ifdef TEST_LONG
    1619static const unsigned long N = 600_000ul;
    1720#else
     
    2326void main(Coroutine& this) {
    2427        while(true) {
    25                 sout | "Coroutine 1" | endl;
     28                #if !defined(TEST_FOREVER)
     29                        sout | "Coroutine 1" | endl;
     30                #endif
    2631                yield();
    27                 sout | "Coroutine 2" | endl;
     32                #if !defined(TEST_FOREVER)
     33                        sout | "Coroutine 2" | endl;
     34                #endif
    2835                suspend();
    2936        }
     
    3340int main(int argc, char* argv[]) {
    3441        Coroutine c;
    35         for(int i = 0; i < N; i++) {
    36                 sout | "Thread 1" | endl;
     42        for(int i = 0; TEST(i < N); i++) {
     43                #if !defined(TEST_FOREVER)
     44                        sout | "Thread 1" | endl;
     45                #endif
    3746                resume(c);
    38                 sout | "Thread 2" | endl;
     47                #if !defined(TEST_FOREVER)
     48                        sout | "Thread 2" | endl;
     49                #endif
    3950                yield();
     51                KICK_WATCHDOG;
    4052        }
    4153}
  • TabularUnified src/tests/concurrent/examples/datingService.c

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

    r0182bfa r28f3a19  
    22#include <thread>
    33#include <time>
     4
     5#include "long_tests.h"
    46
    57#ifndef PREEMPTION_RATE
     
    1113}
    1214
    13 #ifdef LONG_TEST
     15#ifdef TEST_LONG
    1416static const unsigned long N = 30_000ul;
    1517#else
     
    3032
    3133void main(worker_t & this) {
    32         while(counter < N) {
     34        while(TEST(counter < N)) {
    3335                __cfaabi_check_preemption();
    3436                if( (counter % 7) == this.value ) {
     
    4042                }
    4143                __cfaabi_check_preemption();
     44                KICK_WATCHDOG;
    4245        }
    4346}
  • TabularUnified src/tests/concurrent/signal/block.c

    r0182bfa r28f3a19  
    1414#include <time>
    1515
     16#include "long_tests.h"
     17
    1618#ifndef PREEMPTION_RATE
    1719#define PREEMPTION_RATE 10`ms
     
    2224}
    2325
    24 #ifdef LONG_TEST
     26#ifdef TEST_LONG
    2527static const unsigned long N = 150_000ul;
    2628#else
     
    4042}
    4143
    42 void ^?{} ( global_data_t & this ) {}
     44void ^?{} ( global_data_t & mutex this ) {}
    4345
    4446global_data_t globalA, globalB;
     
    6668thread Waiter {};
    6769void main( Waiter & this ) {
    68         for( int i = 0; i < N; i++ ) {
     70        for( int i = 0; TEST(i < N); i++ ) {
    6971                wait_op( globalA, globalB, i );
     72                KICK_WATCHDOG;
    7073        }
    7174}
  • TabularUnified src/tests/concurrent/signal/disjoint.c

    r0182bfa r28f3a19  
    44#include <thread>
    55#include <time>
     6
     7#include "long_tests.h"
    68
    79#ifndef PREEMPTION_RATE
     
    1315}
    1416
    15 #ifdef LONG_TEST
     17#ifdef TEST_LONG
    1618static const unsigned long N = 300_000ul;
    1719#else
     
    2628monitor global_data_t;
    2729void ?{}( global_data_t & this );
    28 void ^?{} ( global_data_t & this );
     30void ^?{} ( global_data_t & mutex this );
    2931
    3032monitor global_data_t {
     
    4244}
    4345
    44 void ^?{} ( global_data_t & this ) {}
     46void ^?{} ( global_data_t & mutex this ) {}
    4547
    4648//------------------------------------------------------------------------------
     
    6769        }
    6870
    69         d.counter++;
     71        #if !defined(TEST_FOREVER)
     72                d.counter++;
     73                if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
     74        #endif
    7075
    71         if( (d.counter % 1000) == 0 ) sout | d.counter | endl;
    72 
    73         return d.counter < N;
     76        return TEST(d.counter < N);
    7477}
    7578
     
    7780
    7881void main( Waiter & this ) {
    79         while( wait( mut, data ) ) { yield(); }
     82        while( wait( mut, data ) ) { KICK_WATCHDOG; yield(); }
    8083}
    8184
     
    9497
    9598        //This is technically a mutual exclusion violation but the mutex monitor protects us
    96         bool running = data.counter < N && data.counter > 0;
     99        bool running = TEST(data.counter < N) && data.counter > 0;
    97100        if( data.state != SIGNAL && running ) {
    98101                sout | "ERROR Eager signal" | data.state | endl;
  • TabularUnified src/tests/concurrent/signal/wait.c

    r0182bfa r28f3a19  
    1212#include <time>
    1313
     14#define __kick_rate 12000ul
     15#include "long_tests.h"
     16
    1417#ifndef PREEMPTION_RATE
    1518#define PREEMPTION_RATE 10`ms
     
    2023}
    2124
    22 #ifdef LONG_TEST
     25#ifdef TEST_LONG
    2326static const unsigned long N = 375_000ul;
    2427#else
     
    9093// Waiter ABC
    9194void main( WaiterABC & this ) {
    92         for( int i = 0; i < N; i++ ) {
     95        for( int i = 0; TEST(i < N); i++ ) {
    9396                wait( condABC, globalA, globalB, globalC );
     97                KICK_WATCHDOG;
    9498        }
    9599
     
    100104// Waiter AB
    101105void main( WaiterAB & this ) {
    102         for( int i = 0; i < N; i++ ) {
     106        for( int i = 0; TEST(i < N); i++ ) {
    103107                wait( condAB , globalA, globalB );
     108                KICK_WATCHDOG;
    104109        }
    105110
     
    110115// Waiter AC
    111116void main( WaiterAC & this ) {
    112         for( int i = 0; i < N; i++ ) {
     117        for( int i = 0; TEST(i < N); i++ ) {
    113118                wait( condAC , globalA, globalC );
     119                KICK_WATCHDOG;
    114120        }
    115121
     
    120126// Waiter BC
    121127void main( WaiterBC & this ) {
    122         for( int i = 0; i < N; i++ ) {
     128        for( int i = 0; TEST(i < N); i++ ) {
    123129                wait( condBC , globalB, globalC );
     130                KICK_WATCHDOG;
    124131        }
    125132
  • TabularUnified src/tests/ifwhileCtl.c

    r0182bfa r28f3a19  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ifcond.c --
     7// ifwhileCtl.c --
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Aug 26 10:13:11 2017
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri Sep 01 15:22:19 2017
    13 // Update Count     : 14
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jun  6 17:15:09 2018
     13// Update Count     : 21
    1414//
    1515
     
    4040                sout | "x != y incorrect" | endl;
    4141        } // if
     42
     43        if ( struct S { int i; } s = { 3 }; s.i < 4 ) {
     44                S s1;
     45                sout | "s.i < 4 correct" | endl;
     46        } else {
     47                S s1;
     48                sout | "s.i >= 4 incorrect" | endl;
     49        } // if
     50
     51        while ( int x = 1 ) {
     52                sout | "x != 0 correct" | endl;
     53                break;
     54        } // while
     55
     56        while ( int x = 4, y = 0 ) {
     57                sout | "x != 0 && y != 0 incorrect" | endl;
     58        } // while
     59
     60        while ( int x = 5, y = f( x ); x == y ) {
     61                sout | "x == y correct" | endl;
     62                break;
     63        } // while
     64
     65        while ( struct S { int i; } s = { 3 }; s.i < 4 ) {
     66                S s1;
     67                sout | "s.i < 4 correct" | endl;
     68                break;
     69        } // while
    4270} // main
    4371
    4472// Local Variables: //
    4573// tab-width: 4 //
    46 // compile-command: "cfa ifcond.c" //
     74// compile-command: "cfa ifwhileCtl.c" //
    4775// End: //
  • TabularUnified src/tests/preempt_longrun/Makefile.am

    r0182bfa r28f3a19  
    1919preempt=10ul\`ms
    2020debug=-debug
     21type=LONG
    2122
    2223REPEAT = ${abs_top_srcdir}/tools/repeat
     24WATCHDOG = ${abs_top_srcdir}/tools/watchdog
    2325TIME = /usr/bin/time -f "%E"
    2426
    25 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
     27# $(shell ./update-type $(type))
     28# ./update-type $(type)
     29
     30UPDATED_TYPE = $(shell ./update-type $(type))
     31
     32BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
    2633CFLAGS = ${BUILD_FLAGS}
    2734CC = @CFA_BINDIR@/@CFA_NAME@
     
    2936TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
    3037
    31 .INTERMEDIATE: ${TESTS}
     38# .INTERMEDIATE: ${TESTS}
    3239
    3340all-local: ${TESTS:=.run}
    3441
     42runall : ${TESTS:=.run}
     43        @ echo "All programs terminated normally"
     44
     45watchall : ${TESTS:=.watch}
     46        @ echo "All programs terminated normally"
     47
     48compileall : ${TESTS}
     49        @ echo "Compiled"
     50
    3551clean-local:
    36         rm -f ${TESTS}
     52        rm -f ${TESTS} core* out.log .type
    3753
    38 % : %.c ${CC}
     54% : %.c ${CC} ${UPDATED_TYPE}
    3955        ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
    4056
    4157%.run : % ${REPEAT}
    4258        @ 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} ./${<}
    4364        @ rm ${<}
    4465        @ echo -e "${<}: SUCCESS\n"
     
    4970        @ echo -e "${<}: SUCCESS\n"
    5071
    51 ${REPEAT}:
     72${REPEAT}: ${abs_top_srcdir}/tools/Makefile
    5273        @+make -C ${abs_top_srcdir}/tools/
     74
     75${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
     76        @+make -C ${abs_top_srcdir}/tools/
  • TabularUnified src/tests/preempt_longrun/Makefile.in

    r0182bfa r28f3a19  
    452452preempt = 10ul\`ms
    453453debug = -debug
     454type = LONG
    454455REPEAT = ${abs_top_srcdir}/tools/repeat
     456WATCHDOG = ${abs_top_srcdir}/tools/watchdog
    455457TIME = /usr/bin/time -f "%E"
    456 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -DLONG_TEST
     458
     459# $(shell ./update-type $(type))
     460# ./update-type $(type)
     461UPDATED_TYPE = $(shell ./update-type $(type))
     462BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt} -I.. -I. -DTEST_$(shell cat .type | tr a-z A-Z)
    457463TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
    458464all: all-am
     
    873879
    874880
    875 .INTERMEDIATE: ${TESTS}
     881# .INTERMEDIATE: ${TESTS}
    876882
    877883all-local: ${TESTS:=.run}
    878884
     885runall : ${TESTS:=.run}
     886        @ echo "All programs terminated normally"
     887
     888watchall : ${TESTS:=.watch}
     889        @ echo "All programs terminated normally"
     890
     891compileall : ${TESTS}
     892        @ echo "Compiled"
     893
    879894clean-local:
    880         rm -f ${TESTS}
    881 
    882 % : %.c ${CC}
     895        rm -f ${TESTS} core* out.log .type
     896
     897% : %.c ${CC} ${UPDATED_TYPE}
    883898        ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
    884899
     
    888903        @ echo -e "${<}: SUCCESS\n"
    889904
     905%.watch : % ${WATCHDOG}
     906        @ time ${WATCHDOG} ./${<}
     907        @ rm ${<}
     908        @ echo -e "${<}: SUCCESS\n"
     909
    890910%.time : % ${REPEAT}
    891911        @ ${REPEAT} -i -s -- $(repeats) $(TIME) -a -o times.log ./${<}
     
    893913        @ echo -e "${<}: SUCCESS\n"
    894914
    895 ${REPEAT}:
     915${REPEAT}: ${abs_top_srcdir}/tools/Makefile
     916        @+make -C ${abs_top_srcdir}/tools/
     917
     918${WATCHDOG}: ${abs_top_srcdir}/tools/Makefile
    896919        @+make -C ${abs_top_srcdir}/tools/
    897920
  • TabularUnified src/tests/preempt_longrun/create.c

    r0182bfa r28f3a19  
    22#include <thread>
    33#include <time>
     4
     5#include "long_tests.h"
    46
    57#ifndef PREEMPTION_RATE
     
    1921int main(int argc, char* argv[]) {
    2022        processor p;
    21         for(int i = 0; i < N; i++) {
     23        for(int i = 0; TEST(i < N); i++) {
    2224                worker_t w[7];
     25                KICK_WATCHDOG;
    2326        }
    2427}
  • TabularUnified src/tests/preempt_longrun/enter.c

    r0182bfa r28f3a19  
    33#include <thread>
    44#include <time>
     5
     6#define __kick_rate 75000ul
     7#include "long_tests.h"
    58
    69#ifndef PREEMPTION_RATE
     
    1518
    1619monitor mon_t {};
     20void foo( mon_t & mutex this ) {
     21        KICK_WATCHDOG;
     22}
    1723
    1824mon_t mon;
    19 
    20 void foo( mon_t & mutex this ) {}
    21 
    2225thread worker_t {};
    23 
    2426void main( worker_t & this ) {
    25         for( unsigned long i = 0; i < N; i++ ) {
     27        for( unsigned long i = 0; TEST(i < N); i++ ) {
    2628                foo( mon );
    2729        }
    28 }
    29 
    30 extern "C" {
    31 static worker_t * workers;
    3230}
    3331
     
    3634        {
    3735                worker_t w[7];
    38                 workers = w;
    3936        }
    4037}
  • TabularUnified src/tests/preempt_longrun/enter3.c

    r0182bfa r28f3a19  
    33#include <thread>
    44#include <time>
     5
     6#define __kick_rate 75000ul
     7#include "long_tests.h"
    58
    69#ifndef PREEMPTION_RATE
     
    1821mon_t mon1, mon2, mon3;
    1922
    20 void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {}
     23void foo( mon_t & mutex a, mon_t & mutex b, mon_t & mutex c ) {
     24        KICK_WATCHDOG;
     25}
    2126
    2227thread worker_t {};
    2328
    2429void main( worker_t & this ) {
    25         for( unsigned long i = 0; i < N; i++ ) {
     30        for( unsigned long i = 0; TEST(i < N); i++ ) {
    2631                foo( mon1, mon2, mon3 );
    2732        }
  • TabularUnified src/tests/preempt_longrun/processor.c

    r0182bfa r28f3a19  
    22#include <thread>
    33#include <time>
     4
     5#include <unistd.h>
     6
     7#include "long_tests.h"
    48
    59#ifndef PREEMPTION_RATE
     
    1115}
    1216
    13 static const unsigned long N = 5_000ul;
     17static const unsigned long N = 50_000ul;
    1418
    1519int main(int argc, char* argv[]) {
     
    1822                p[pi] = new();
    1923        }
    20         for ( int i = 0; i < N; i++) {
     24        for ( int i = 0; TEST(i < N); i++) {
    2125                int pi = i % 15;
    2226                delete( p[pi] );
    2327                p[pi] = new();
     28                KICK_WATCHDOG;
     29        }
     30        for ( int pi = 0; pi < 15; pi++ ) {
     31                delete( p[pi] );
    2432        }
    2533}
  • TabularUnified src/tests/preempt_longrun/stack.c

    r0182bfa r28f3a19  
    33#include <thread>
    44#include <time>
     5
     6#define __kick_rate 5000000ul
     7#include "long_tests.h"
    58
    69#ifndef PREEMPTION_RATE
     
    1518
    1619void main(worker_t & this) {
    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         }
     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                }
    2429
    25         if( n != a ) {
    26                 abort();
     30                if( !TEST(n == a) ) {
     31                        abort();
     32                }
    2733        }
    2834}
  • TabularUnified src/tests/preempt_longrun/yield.c

    r0182bfa r28f3a19  
    22#include <thread>
    33#include <time>
     4
     5#define __kick_rate 550000ul
     6#include "long_tests.h"
    47
    58#ifndef PREEMPTION_RATE
     
    1114}
    1215
    13 #ifdef LONG_TEST
     16#ifdef TEST_LONG
    1417static const unsigned long N = 9_750_000ul;
    1518#else
     
    2023
    2124void main(worker_t & this) {
    22         for(int i = 0; i < N; i++) {
     25        for(int i = 0; TEST(i < N); i++) {
    2326                yield();
     27                KICK_WATCHDOG;
    2428        }
    2529}
  • TabularUnified src/tests/pybin/tools.py

    r0182bfa r28f3a19  
    8383        return sh(cmd)
    8484
     85def 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
    85101################################################################################
    86102#               file handling
     
    219235        return False
    220236
     237def 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)
    221246
    222247settings.set_machine_default( getMachineType )
  • TabularUnified src/tests/raii/.expect/ctor-autogen-ERR1.txt

    r0182bfa r28f3a19  
    1 raii/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)
     1raii/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
    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
  • TabularUnified src/tests/sum.c

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

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

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

    r0182bfa r28f3a19  
    9292build_triplet = @build@
    9393host_triplet = @host@
    94 noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT)
     94noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT) \
     95        watchdog$(EXEEXT)
    9596subdir = tools
    9697ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
     
    115116repeat_OBJECTS = $(am_repeat_OBJECTS)
    116117repeat_LDADD = $(LDADD)
     118am_watchdog_OBJECTS = watchdog.$(OBJEXT)
     119watchdog_OBJECTS = $(am_watchdog_OBJECTS)
     120watchdog_LDADD = $(LDADD)
    117121AM_V_P = $(am__v_P_@AM_V@)
    118122am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    143147am__v_CCLD_0 = @echo "  CCLD    " $@;
    144148am__v_CCLD_1 =
    145 SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
    146 DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
     149SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
     150        $(watchdog_SOURCES)
     151DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
     152        $(watchdog_SOURCES)
    147153am__can_run_installinfo = \
    148154  case $$AM_UPDATE_INFO_DIR in \
     
    295301catchsig_SOURCES = catchsig.c
    296302repeat_SOURCES = repeat.c
     303watchdog_SOURCES = watchdog.c
    297304all: all-am
    298305
     
    344351        $(AM_V_CCLD)$(LINK) $(repeat_OBJECTS) $(repeat_LDADD) $(LIBS)
    345352
     353watchdog$(EXEEXT): $(watchdog_OBJECTS) $(watchdog_DEPENDENCIES) $(EXTRA_watchdog_DEPENDENCIES)
     354        @rm -f watchdog$(EXEEXT)
     355        $(AM_V_CCLD)$(LINK) $(watchdog_OBJECTS) $(watchdog_LDADD) $(LIBS)
     356
    346357mostlyclean-compile:
    347358        -rm -f *.$(OBJEXT)
     
    353364@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catchsig.Po@am__quote@
    354365@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@
     366@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
    355367
    356368.c.o:
  • TabularUnified tools/prettyprinter/lex.ll

    r0182bfa r28f3a19  
    1010 * Created On       : Sat Dec 15 11:45:59 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sun Apr 15 21:28:33 2018
    13  * Update Count     : 271
     12 * Last Modified On : Thu May 31 08:49:58 2018
     13 * Update Count     : 274
    1414 */
    1515
     
    7777}
    7878
    79 <INITIAL,C_CODE>"//"[^\n]*"\n" {                                                // C++ style comments
     79<INITIAL,C_CODE>"//"[^\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.