Changes in / [a556492:9ef9644]


Ignore:
Files:
4 added
2 deleted
31 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    ra556492 r9ef9644  
    161161                Tools.BuildStage('Test: full', Settings.RunAllTests) {
    162162                        dir (BuildDir) {
     163                                        jopt = ""
     164                                        if( Settings.Architecture.node == 'x86' ) {
     165                                                jopt = "-j2"
     166                                        }
    163167                                        //Run the tests from the tests directory
    164                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
    165                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
     168                                        sh """make ${jopt} --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
     169                                        sh """make ${jopt} --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
    166170                        }
    167171                }
  • benchmark/io/http/Makefile.am

    ra556492 r9ef9644  
    5050.dummy_hackxx.cpp:
    5151        @echo "int bar() { return 0; }" > ${@}
     52
     53# add dependency of cfa files
     54nodist_httpforall_OBJECTS = $(addsuffix .o, $(basename $(filter %.cfa,$(nodist_httpforall_SOURCES))))
     55$(nodist_httpforall_OBJECTS) : @CFACC@ @CFACPP@
     56
     57# .deps inclusion is not done automatically by automake for new languages
     58nodist_httpforall_DEPENDS = $(join \
     59        $(addsuffix $(DEPDIR)/ , $(dir $(nodist_httpforall_OBJECTS) ) ), \
     60        $(notdir ${nodist_httpforall_OBJECTS:.o=.Po}) \
     61)
     62
     63-include $(nodist_httpforall_DEPENDS)
     64
     65list_libdeps:
     66        echo "objects: " $(nodist_httpforall_OBJECTS)
     67        echo "depends: " $(nodist_httpforall_DEPENDS)
  • doc/user/user.tex

    ra556492 r9ef9644  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Oct 10 12:45:00 2021
    14 %% Update Count     : 5095
     13%% Last Modified On : Sat Feb 12 17:04:03 2022
     14%% Update Count     : 5376
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
    1717% requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended
    1818
    19 \documentclass[twoside,11pt]{article}
     19\documentclass[twoside]{article}
    2020
    2121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    4040% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    4141% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    42 % LaTex escape §...§ (section symbol) emacs: C-q M-'
     42% LaTex escape ...§ (section symbol) emacs: C-q M-'
    4343% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    4444% math escape $...$ (dollar symbol)
     
    8585\newcommand{\B}[1]{{\Textbf[blue]{#1}}}
    8686\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
     87\newcommand{\Sp}{\R{\textvisiblespace}}
    8788\newcommand{\KWC}{K-W C\xspace}
    8889
     
    156157One of the main design philosophies of \CFA is to ``\Index{describe not prescribe}'', which means \CFA tries to provide a pathway from low-level C programming to high-level \CFA programming, but it does not force programmers to ``do the right thing''.
    157158Programmers can cautiously add \CFA extensions to their C programs in any order and at any time to incrementally move towards safer, higher-level programming.
    158 A programmer is always free to reach back to C from \CFA, for any reason, and in many cases, new \CFA features can be locally switched back to there C counterpart.
    159 There is no notion or requirement for \emph{rewriting} a legacy C program in \CFA;
     159A programmer is always free to reach back to C from \CFA, for any reason, and in many cases, new \CFA features can be locally switched back to their C counterpart.
     160There is no notion or requirement for \emph{rewriting} a legacy C program to \CFA;
    160161instead, a programmer evolves a legacy program into \CFA by incrementally incorporating \CFA features.
    161162As well, new programs can be written in \CFA using a combination of C and \CFA features.
     
    163164
    164165\Index*[C++]{\CC{}}~\cite{c++:v1} had a similar goal 30 years ago, allowing object-oriented programming to be incrementally added to C.
    165 However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that cannot be updated, and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
     166However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that are difficult to update, and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
    166167In contrast, \CFA has 30 years of hindsight and a clean starting point.
    167168
    168169Like \Index*[C++]{\CC{}}, there may be both old and new ways to achieve the same effect.
    169170For example, the following programs compare the C, \CFA, and \CC I/O mechanisms, where the programs output the same result.
    170 \begin{center}
     171\begin{flushleft}
    171172\begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    172 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}}   & \multicolumn{1}{c}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{\CC}}      \\
    173 \begin{cfa}
     173\multicolumn{1}{@{}c@{\hspace{1em}}}{\textbf{C}}        & \multicolumn{1}{c}{\textbf{\CFA}}     & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
     174\begin{cfa}[tabsize=3]
    174175#include <stdio.h>$\indexc{stdio.h}$
    175176
     
    180181\end{cfa}
    181182&
    182 \begin{cfa}
     183\begin{cfa}[tabsize=3]
    183184#include <fstream>$\indexc{fstream}$
    184185
     
    189190\end{cfa}
    190191&
    191 \begin{cfa}
     192\begin{cfa}[tabsize=3]
    192193#include <iostream>$\indexc{iostream}$
    193194using namespace std;
    194195int main() {
    195196        int x = 0, y = 1, z = 2;
    196         ®cout<<x<<" "<<y<<" "<<z<<endl;®
     197        ®cout << x << ' ' << y << ' ' << z << endl;®
    197198}
    198199\end{cfa}
    199200\end{tabular}
    200 \end{center}
     201\end{flushleft}
    201202While \CFA I/O \see{\VRef{s:StreamIOLibrary}} looks similar to \Index*[C++]{\CC{}}, there are important differences, such as automatic spacing between variables and an implicit newline at the end of the expression list, similar to \Index*{Python}~\cite{Python}.
    202203
     
    238239however, it largely extended the C language, and did not address many of C's existing problems.\footnote{%
    239240Two important existing problems addressed were changing the type of character literals from ©int© to ©char© and enumerator from ©int© to the type of its enumerators.}
    240 \Index*{Fortran}~\cite{Fortran08}, \Index*{Ada}~\cite{Ada12}, and \Index*{Cobol}~\cite{Cobol14} are examples of programming languages that took an evolutionary approach, where modern language-features (\eg objects, concurrency) are added and problems fixed within the framework of the existing language.
     241\Index*{Fortran}~\cite{Fortran08}, \Index*{Cobol}~\cite{Cobol14}, and \Index*{Ada}~\cite{Ada12} are examples of programming languages that took an evolutionary approach, where modern language-features (\eg objects, concurrency) are added and problems fixed within the framework of the existing language.
    241242\Index*{Java}~\cite{Java8}, \Index*{Go}~\cite{Go}, \Index*{Rust}~\cite{Rust} and \Index*{D}~\cite{D} are examples of the revolutionary approach for modernizing C/\CC, resulting in a new language rather than an extension of the descendent.
    242243These languages have different syntax and semantics from C, do not interoperate directly with C, and are not systems languages because of restrictive memory-management or garbage collection.
     
    333334long double _Complex ®abs®( long double _Complex );
    334335\end{cfa}
    335 The problem is \Index{name clash} between the C name ©abs© and the \CFA names ©abs©, resulting in two name linkages\index{C linkage}: ©extern "C"© and ©extern "Cforall"© (default).
     336The problem is a \Index{name clash} between the C name ©abs© and the \CFA names ©abs©, resulting in two name linkages\index{C linkage}: ©extern "C"© and ©extern "Cforall"© (default).
    336337Overloaded names must use \newterm{name mangling}\index{mangling!name} to create unique names that are different from unmangled C names.
    337338Hence, there is the same need as in \CC to know if a name is a C or \CFA name, so it can be correctly formed.
     
    377378The program is linked with the debugging version of the runtime system.
    378379The debug version performs runtime checks to aid the debugging phase of a \CFA program, but can substantially slow program execution.
    379 The runtime checks should only be removed after the program is completely debugged.
     380The runtime checks should only be removed after a program is completely debugged.
    380381\textbf{This option is the default.}
    381382
     
    452453cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude
    453454\end{lstlisting}
     455Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces.
     456\begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}]
     457cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude
     458\end{lstlisting}
    454459\begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt]
    455460\item
     
    533538double ®``®forall = 3.5;
    534539\end{cfa}
    535 
    536 Existing C programs with keyword clashes can be converted by enclosing keyword identifiers in backquotes, and eventually the identifier name can be changed to a non-keyword name.
     540Existing C programs with keyword clashes can be converted by prefixing the keyword identifiers with double backquotes, and eventually the identifier name can be changed to a non-keyword name.
    537541\VRef[Figure]{f:HeaderFileInterposition} shows how clashes in existing C header-files \see{\VRef{s:StandardHeaders}} can be handled using preprocessor \newterm{interposition}: ©#include_next© and ©-I filename©.
    538542Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience.
     
    627631\subsection{\texorpdfstring{\LstKeywordStyle{if} / \LstKeywordStyle{while} Statement}{if / while Statement}}
    628632
    629 The ©if©/©while© expression allows declarations, similar to ©for© declaration expression.\footnote{
    630 Declarations in the ©do©-©while© condition are not useful because they appear after the loop body.}
     633The \Indexc{if}/\Indexc{while} expression allows declarations, similar to \Indexc{for} declaration expression.\footnote{
     634Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.}
    631635\begin{cfa}
    632636if ( ®int x = f()® ) ... $\C{// x != 0}$
     
    640644while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$
    641645\end{cfa}
    642 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical ©&&© operator.
    643 The scope of the declaration(s) is local to the ©if© statement but exist within both the \emph{then} and \emph{else} clauses.
     646Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical \Indexc{&&} operator.
     647The scope of the declaration(s) is local to the ©if©/©while© statement, \ie in both \emph{then} and \emph{else} clauses for ©if©, and loop body for ©while©.
    644648\CC only provides a single declaration always compared ©!=© to 0.
    645649
     
    649653\label{s:caseClause}
    650654
    651 C restricts the ©case© clause of a ©switch© statement to a single value.
     655C restricts the \Indexc{case} clause of a \Indexc{switch} statement to a single value.
    652656For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values.
    653 Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
    654 Therefore, the ©case© clause is extended with a list of values, as in:
     657Requiring a ©case© clause for each value is not in the spirit of brevity normally associated with C.
     658Therefore, the ©case© clause is extended with a list of values.
    655659\begin{cquote}
    656660\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     
    703707\subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}}
    704708
    705 C allows a number of questionable forms for the ©switch© statement:
     709C allows a number of questionable forms for the \Indexc{switch} statement:
    706710\begin{enumerate}
    707711\item
    708 By default, the end of a ©case© clause\footnote{
     712By default, the end of a \Indexc{case} clause\footnote{
    709713In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.}
    710714\emph{falls through} to the next ©case© clause in the ©switch© statement;
    711 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:
     715to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly \Indexc{break}:
    712716\begin{cfa}
    713717switch ( i ) {
    714718  case 1:
    715719        ...
    716         // fall-through
     720        $\R{\LstCommentStyle{// fall-through}}$
    717721  case 2:
    718722        ...
    719         break;  // exit switch statement
     723        ®break;®        // exit switch statement
    720724}
    721725\end{cfa}
     
    763767}
    764768\end{cfa}
    765 This situation better handled without fall-through by allowing a list of case values \see{\VRef{s:caseClause}}.
     769This situation is better handled by a list of case values \see{\VRef{s:caseClause}}.
    766770While fall-through itself is not a problem, the problem occurs when fall-through is the default, as this semantics is unintuitive to many programmers and is different from most programming languages with a ©switch© statement.
    767771Hence, default fall-through semantics results in a large number of programming errors as programmers often \emph{forget} the ©break© statement at the end of a ©case© clause, resulting in inadvertent fall-through.
     
    777781                ...
    778782        } // if
    779   case 2:
    780         while ( j < 5 ) {
    781                 ...
    782           ®case 3:®             // transfer into "while" statement
    783                 ...
    784         } // while
    785 } // switch
    786783\end{cfa}
    787784This usage branches into control structures, which is known to cause both comprehension and technical difficulties.
     
    789786The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning.
    790787There are few arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it.
    791 Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}:
     788
     789This C idiom is known as ``\Index*{Duff's device}''~\cite{Duff83}, from this example:
    792790\begin{cfa}
    793791register int n = (count + 7) / 8;
     
    858856still works.
    859857Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments.
    860 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg:
     858Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called \Indexc{choose}, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword \Indexc{fallthrough}/\Indexc{fallthru}, \eg:
    861859\begin{cfa}
    862860®choose® ( i ) {
     
    885883Therefore, no change is made for this issue.
    886884\item
    887 Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and associated initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{
     885Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{
    888886Essentially, these declarations are hoisted before the ©switch©/©choose© statement and both declarations and statement are surrounded by a compound statement.} and precluding statements before the first ©case© clause.
    889887Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound.
     
    908906\subsection{Non-terminating and Labelled \texorpdfstring{\LstKeywordStyle{fallthrough}}{Non-terminating and Labelled fallthrough}}
    909907
    910 The ©fallthrough© clause may be non-terminating within a ©case© clause or have a target label to common code from multiple case clauses.
     908The \Indexc{fallthrough} clause may be non-terminating within a \Indexc{case} clause or have a target label to common code from multiple case clauses.
    911909\begin{center}
    912910\begin{tabular}{@{}lll@{}}
     
    960958\end{tabular}
    961959\end{center}
    962 The target label must be below the ©fallthrough© and may not be nested in a control structure, and
    963 the target label must be at the same or higher level as the containing ©case© clause and located at
    964 the same level as a ©case© clause; the target label may be case ©default©, but only associated
    965 with the current ©switch©/©choose© statement.
     960The target label must be below the \Indexc{fallthrough} and may not be nested in a control structure, and
     961the target label must be at the same or higher level as the containing \Indexc{case} clause and located at
     962the same level as a ©case© clause; the target label may be case \Indexc{default}, but only associated
     963with the current \Indexc{switch}/\Indexc{choose} statement.
    966964
    967965\begin{figure}
     
    10761074Looping a fixed number of times, possibly with a loop index, occurs frequently.
    10771075\CFA condenses simply looping to facilitate coding speed and safety.
    1078 The ©for©/©while©/©do-while© loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}:
     1076The \Indexc{for}, \Indexc{while}, and \Indexc{do} loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}:
    10791077\begin{itemize}[itemsep=0pt]
    10801078\item
     
    11451143\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
    11461144
    1147 C ©continue© and ©break© statements, for altering control flow, are restricted to one level of nesting for a particular control structure.
     1145C \Indexc{continue} and \Indexc{break} statements, for altering control flow, are restricted to one level of nesting for a particular control structure.
    11481146This restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting.
    11491147To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java.
    1150 For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement;
    1151 for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
     1148For both ©continue© and ©break©, the target label must be directly associated with a \Indexc{for}, \Indexc{while} or \Indexc{do} statement;
     1149for ©break©, the target label can also be associated with a \Indexc{switch}, \Indexc{if} or compound (©{}©) statement.
    11521150\VRef[Figure]{f:MultiLevelExit} shows a comparison between labelled ©continue© and ©break© and the corresponding C equivalent using ©goto© and labels.
    11531151The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     
    12241222\end{figure}
    12251223
    1226 Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways:
     1224Both labelled \Indexc{continue} and \Indexc{break} are a \Indexc{goto}\index{goto@©goto©!restricted} restricted in the following ways:
    12271225\begin{itemize}
    12281226\item
     
    12401238
    12411239
     1240\subsection{\texorpdfstring{Extended \LstKeywordStyle{else}}{Extended else}}
     1241\label{s:ExtendedElse}
     1242\index{extended ©else©}
     1243
     1244The ©if© statement has an optional ©else© clause executed if the conditional is false.
     1245This concept is extended to the \Indexc{while}, \Indexc{for}, and \Indexc{do} looping constructs (like Python).
     1246Hence, if the loop conditional becomes false, looping stops and the corresponding ©else© clause is executed, if present.
     1247
     1248The following example is a linear search for the key 3 in an array, where finding the key is handled with a ©break© and not finding with the ©else© clause on the loop construct.
     1249\begin{cquote}
     1250\begin{cfa}
     1251int a[10];
     1252\end{cfa}
     1253\begin{tabular}{@{}lll@{}}
     1254\begin{cfa}
     1255
     1256while ( int i = 0; i < 10 ) {
     1257  if ( a[i] == 3 ) break; // found
     1258        i += 1;
     1259} ®else® { // i == 10
     1260        sout | "not found";
     1261}
     1262\end{cfa}
     1263&
     1264\begin{cfa}
     1265
     1266for ( i; 10 ) {
     1267  if ( a[i] == 3 ) break; // found
     1268
     1269} ®else® { // i == 10
     1270        sout | "not found";
     1271}
     1272\end{cfa}
     1273&
     1274\begin{cfa}
     1275int i = 0;
     1276do {
     1277  if ( a[i] == 3 ) break; // found
     1278        i += 1;
     1279} while( i < 10 ) ®else® { // i == 10
     1280        sout | "not found";
     1281}
     1282\end{cfa}
     1283\end{tabular}
     1284\end{cquote}
     1285Note, \Index{dangling else} now occurs with \Indexc{if}, \Indexc{while}, \Indexc{for}, \Indexc{do}, and \Indexc{waitfor}.
     1286
     1287
    12421288%\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}}
    12431289\subsection{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}}
     
    12661312Therefore, reducing aggregate qualification is a useful language design goal.
    12671313
    1268 C allows unnamed nested aggregates that open their scope into the containing aggregate.
     1314C partially addresses the problem by eliminating qualification for enumerated types and unnamed \emph{nested} aggregates, which open their scope into the containing aggregate.
    12691315This feature is used to group fields for attributes and/or with ©union© aggregates.
    12701316\begin{cfa}
    12711317struct S {
    1272         struct { int g,  h; } __attribute__(( aligned(64) ));
     1318        struct $\R{\LstCommentStyle{/* unnamed */}}$ { int g,  h; } __attribute__(( aligned(64) ));
    12731319        int tag;
    1274         union {
     1320        union $\R{\LstCommentStyle{/* unnamed */}}$ {
    12751321                struct { char c1,  c2; } __attribute__(( aligned(128) ));
    12761322                struct { int i1,  i2; };
    12771323                struct { double d1,  d2; };
    12781324        };
    1279 };
    1280 s.g; s.h; s.tag; s.c1; s.c2; s.i1; s.i2; s.d1; s.d2;
     1325} s;
     1326enum { R, G, B };
     1327s.g; s.h;   s.tag = R;   s.c1; s.c2;   s.i1 = G; s.i2 = B;   s.d1; s.d2;
    12811328\end{cfa}
    12821329
     
    13231370\end{cfa}
    13241371where qualification is only necessary to disambiguate the shadowed variable ©i©.
    1325 
    1326 In detail, the ©with© statement may appear as the body of a function or nested within a function body.
     1372In detail, the ©with© statement may form a function body or be nested within a function body.
     1373
    13271374The ©with© clause takes a list of expressions, where each expression provides an aggregate type and object.
    13281375(Enumerations are already opened.)
     
    13331380\end{cfa}
    13341381The expression object is the implicit qualifier for the open structure-fields.
     1382
    13351383\CFA's ability to overload variables \see{\VRef{s:VariableOverload}} and use the left-side of assignment in type resolution means most fields with the same name but different types are automatically disambiguated, eliminating qualification.
    13361384All expressions in the expression list are open in parallel within the compound statement.
     
    13621410\end{cfa}
    13631411A cast or qualification can be used to disambiguate variables within a ©with© \emph{statement}.
    1364 A cast can be used to disambiguate among overload variables in a ©with© \emph{expression}:
     1412A cast can also be used to disambiguate among overload variables in a ©with© \emph{expression}:
    13651413\begin{cfa}
    13661414with ( w ) { ... }                                                      $\C{// ambiguous, same name and no context}$
     
    13711419Finally, there is an interesting problem between parameters and the function-body ©with©, \eg:
    13721420\begin{cfa}
    1373 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$
    1374         ®s.i = i;®  j = 3;  m = 5.5; $\C{// initialize fields}$
    1375 }
    1376 \end{cfa}
    1377 Here, the assignment ©s.i = i© means ©s.i = s.i©, which is meaningless, and there is no mechanism to qualify the parameter ©i©, making the assignment impossible using the function-body ©with©.
    1378 To solve this problem, parameters are treated like an initialized aggregate:
    1379 \begin{cfa}
    1380 struct Params {
    1381         S & s;
    1382         int i;
     1421void f( S & s, char c ) with ( s ) {
     1422        ®s.c = c;®  i = 3;  d = 5.5;                    $\C{// initialize fields}$
     1423}
     1424\end{cfa}
     1425Here, the assignment ©s.c = c© means ©s.c = s.c©, which is meaningless, and there is no mechanism to qualify the parameter ©c©, making the assignment impossible using the function-body ©with©.
     1426To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate:
     1427\begin{cfa}
     1428struct Params {                                                         $\C{// s explicitly opened so S \& s elided}$
     1429        char c;
    13831430} params;
    13841431\end{cfa}
    13851432and implicitly opened \emph{after} a function-body open, to give them higher priority:
    13861433\begin{cfa}
    1387 void ?{}( S & s, int ®i® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only
    1388         s.i = ®i®; j = 3; m = 5.5;
     1434void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only
     1435        s.c = ®c;®  i = 3;  d = 5.5;
    13891436}
    13901437\end{cfa}
    13911438This implicit semantic matches with programmer expectation.
    1392 
    13931439
    13941440
     
    33973443This requirement is the same as for comma expressions in argument lists.
    33983444
    3399 Type qualifiers, \ie const and volatile, may modify a tuple type.
    3400 The meaning is the same as for a type qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], \ie the qualifier is distributed across all of the types in the tuple, \eg:
     3445Type qualifiers, \ie ©const© and ©volatile©, may modify a tuple type.
     3446The meaning is to distribute the qualifier across all of the types in the tuple, \eg:
    34013447\begin{cfa}
    34023448const volatile [ int, float, const int ] x;
     
    35973643Stream ©exit© implicitly returns ©EXIT_FAILURE© to the shell.
    35983644\begin{cfa}
    3599 ®exit®   | "x (" | x | ") negative value."; // terminate and return EXIT_FAILURE to shell
    3600 ®abort® | "x (" | x | ") negative value."; // terminate and generate stack trace and core file
     3645®exit®   | "x (" | x | ") negative value.";   // terminate and return EXIT_FAILURE to shell
     3646®abort® | "x (" | x | ") negative value.";   // terminate and generate stack trace and core file
    36013647\end{cfa}
    36023648Note, \CFA stream variables ©stdin©, ©stdout©, ©stderr©, ©exit©, and ©abort© overload C variables ©stdin©, ©stdout©, ©stderr©, and functions ©exit© and ©abort©, respectively.
     
    42674313        sout | '1' | '2' | '3';
    42684314        sout | 1 | "" | 2 | "" | 3;
    4269         sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
    4270                 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
     4315        sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x Â¥"
     4316                | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
    42714317        sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
    4272                 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";
     4318                | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";
    42734319        sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx";
    42744320        sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4;
     
    44464492The common usage is the short form of the mutex statement\index{ostream@©ostream©!mutex@©mutex©} to lock a stream during a single cascaded I/O expression, \eg:
    44474493\begin{cfa}
    4448 $\emph{thread\(_1\)}$ : ®mutex()® sout | "abc " | "def ";
    4449 $\emph{thread\(_2\)}$ : ®mutex()® sout | "uvw " | "xyz ";
     4494$\emph{thread\(_1\)}$ : ®mutex( sout )® sout | "abc " | "def ";
     4495$\emph{thread\(_2\)}$ : ®mutex( sout )® sout | "uvw " | "xyz ";
    44504496\end{cfa}
    44514497Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order.
     
    44704516®mutex( sout )® {
    44714517        sout | 1;
    4472         ®mutex() sout® | 2 | 3;                         $\C{// unnecessary, but ok because of recursive lock}$
     4518        ®mutex( sout ) sout® | 2 | 3;                           $\C{// unnecessary, but ok because of recursive lock}$
    44734519        sout | 4;
    44744520} // implicitly release sout lock
     
    44824528        int x, y, z, w;
    44834529        sin | x;
    4484         ®mutex() sin® | y | z;                          $\C{// unnecessary, but ok because of recursive lock}$
     4530        ®mutex( sin )® sin | y | z;                                     $\C{// unnecessary, but ok because of recursive lock}$
    44854531        sin | w;
    44864532} // implicitly release sin lock
     
    44914537\Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg:
    44924538\begin{cfa}
    4493 ®mutex() sout® | "data:" | rtn( mon );  $\C{// mutex call on monitor}$
     4539®mutex( sout )® sout | "data:" | rtn( mon );    $\C{// mutex call on monitor}$
    44944540\end{cfa}
    44954541If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it.
     
    44984544\begin{cfa}
    44994545int ®data® = rtn( mon );
    4500 mutex() sout | "data:" | ®data®;
    4501 \end{cfa}
     4546mutex( sout ) sout | "data:" | ®data®;
     4547\end{cfa}
     4548
     4549
     4550\subsection{Locale}
     4551\index{stream!locale}
     4552\index{locale!stream}
     4553
     4554Cultures use different syntax, called a \newterm{locale}, for printing numbers so they are easier to read, \eg:
     4555\begin{cfa}
     455612®,®345®.®123          $\C[1.25in]{// comma separator, period decimal-point}$
     455712®.®345®,®123          $\C{// period separator, comma decimal-point}$
     455812$\Sp$345®,®123®.®     $\C{// space separator, comma decimal-point, period terminator}\CRT$
     4559\end{cfa}
     4560A locale is selected with function ©setlocale©, and the corresponding locale package \emph{must} be installed on the underlying system;
     4561©setlocale© returns ©0p© if the requested locale is unavailable.
     4562Furthermore, a locale covers the syntax for many cultural items, \eg address, measurement, money, etc.
     4563This discussion applies to item ©LC_NUMERIC© for formatting non-monetary integral and floating-point values.
     4564\VRef[Figure]{f:StreamLocale} shows selecting different cultural syntax, which may be associated with one or more countries.
     4565
     4566\begin{figure}
     4567\begin{cfa}
     4568#include <fstream.hfa>
     4569#include <locale.h>                                                     $\C{// setlocale}$
     4570#include <stdlib.h>                                                     $\C{// getenv}$
     4571
     4572int main() {
     4573        void print() {
     4574                sout | 12 | 123 | 1234 | 12345 | 123456 | 1234567;
     4575                sout | 12. | 123.1 | 1234.12 | 12345.123 | 123456.1234 | 1234567.12345;
     4576                sout | nl;
     4577        }
     4578        sout | "Default locale off";
     4579        print();
     4580        sout | "Locale on" | ®setlocale( LC_NUMERIC, getenv( "LANG" ) )®;  // enable local locale
     4581        print();
     4582        sout | "German" | ®setlocale( LC_NUMERIC, "de_DE.UTF-8" )®;  // enable German locale
     4583        print();
     4584        sout | "Ukraine" | ®setlocale( LC_NUMERIC, "uk_UA.utf8" )®;  // enable Ukraine locale
     4585        print();
     4586        sout | "Default locale off" | ®setlocale( LC_NUMERIC, "C" )®;  // disable locale
     4587        print();
     4588}
     4589
     4590Default locale off
     459112 123 1234 12345 123456 1234567
     459212. 123.1 1234.12 12345.123 123456.1234 1234567.12345
     4593
     4594Locale on en_US.UTF-8
     459512 123 1®,®234 12®,®345 123®,®456 1®,®234®,®567
     459612®.® 123®.®1 1®,®234®.®12 12®,®345®.®123 123®,®456®.®1234 1®,®234®,®567®.®12345
     4597
     4598German de_DE.UTF-8
     459912 123 1®.®234 12®.®345 123®.®456 1®.®234®.®567
     460012®.® 123®,®1®.® 1®.®234®,®12 12®.®345®,®123 123®.®456®,®1234 1®.®234®.®567®,®12345
     4601
     4602Ukraine uk_UA.utf8
     460312 123 1 234 12 345 123 456 1 234 567
     460412®.® 123®,®1®.® 1$\Sp$234®,®12®.® 12$\Sp$ 345®,®123®.® 123$\Sp$ 456®,®1234®.® 1$\Sp$ 234$\Sp$567®,®12345®.®
     4605
     4606Default locale off C
     460712 123 1234 12345 123456 1234567
     460812. 123.1 1234.12 12345.123 123456.1234 1234567.12345
     4609\end{cfa}
     4610\caption{Stream Locale}
     4611\label{f:StreamLocale}
     4612\end{figure}
    45024613
    45034614
     
    45554666\end{figure}
    45564667
     4668
    45574669\begin{comment}
    45584670\section{Types}
     
    46374749
    46384750
    4639 \subsection{Structures}
     4751\section{Structures}
    46404752
    46414753Structures in \CFA are basically the same as structures in C.
     
    52705382\subsection{Coroutine}
    52715383
    5272 \Index{Coroutines} are the precursor to tasks.
     5384\Index{Coroutines} are the precursor to threads.
    52735385\VRef[Figure]{f:FibonacciCoroutine} shows a coroutine that computes the \Index*{Fibonacci} numbers.
    52745386
     
    53725484
    53735485
    5374 \subsection{Tasks}
     5486\subsection{Threads}
    53755487
    53765488\CFA also provides a simple mechanism for creating and utilizing user level threads.
    5377 A task provides mutual exclusion like a monitor, and also has its own execution state and a thread of control.
    5378 Similar to a monitor, a task is defined like a structure:
     5489A thread provides mutual exclusion like a monitor, and also has its own execution state and a thread of control.
     5490Similar to a monitor, a thread is defined like a structure:
    53795491
    53805492\begin{figure}
     
    54205532}
    54215533\end{cfa}
    5422 \caption{Simple Tasks}
    5423 \label{f:SimpleTasks}
     5534\caption{Simple Threads}
     5535\label{f:SimpleThreads}
    54245536\end{figure}
    54255537
     
    67886900In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as:
    67896901\begin{cfa}
    6790 *?$\R{\textvisiblespace}$*? $\C{// dereference operator, dereference operator}$
    6791 *$\R{\textvisiblespace}$?*? $\C{// dereference, multiplication operator}$
     6902*?$\Sp$*? $\C{// dereference operator, dereference operator}$
     6903*$\Sp$?*? $\C{// dereference, multiplication operator}$
    67926904\end{cfa}
    67936905By default, the first interpretation is selected, which does not yield a meaningful parse.
     
    68136925Therefore, it is necessary to disambiguate these cases with a space:
    68146926\begin{cfa}
    6815 i++$\R{\textvisiblespace}$? i : 0;
    6816 i?$\R{\textvisiblespace}$++i : 0;
     6927i++$\Sp$? i : 0;
     6928i?$\Sp$++i : 0;
    68176929\end{cfa}
    68186930
     
    74307542char random( void );$\indexc{random}$
    74317543char random( char u ); $\C{// [0,u)}$
    7432 char random( char l, char u ); $\C{// [l,u)}$
     7544char random( char l, char u ); $\C{// [l,u]}$
    74337545int random( void );
    74347546int random( int u ); $\C{// [0,u)}$
    7435 int random( int l, int u ); $\C{// [l,u)}$
     7547int random( int l, int u ); $\C{// [l,u]}$
    74367548unsigned int random( void );
    74377549unsigned int random( unsigned int u ); $\C{// [0,u)}$
    7438 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u)}$
     7550unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u]}$
    74397551long int random( void );
    74407552long int random( long int u ); $\C{// [0,u)}$
    7441 long int random( long int l, long int u ); $\C{// [l,u)}$
     7553long int random( long int l, long int u ); $\C{// [l,u]}$
    74427554unsigned long int random( void );
    74437555unsigned long int random( unsigned long int u ); $\C{// [0,u)}$
    7444 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u)}$
     7556unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u]}$
    74457557float random( void );                                            $\C{// [0.0, 1.0)}$
    74467558double random( void );                                           $\C{// [0.0, 1.0)}$
     
    81068218
    81078219
     8220\section{Pseudo Random Number Generator}
     8221\label{s:PRNG}
     8222
     8223Random numbers are values generated independently, i.e., new values do not depend on previous values (independent trials), \eg lottery numbers, shuffled cards, dice roll, coin flip.
     8224While a primary goal of programming is computing values that are \emph{not} random, random values are useful in simulation, cryptography, games, etc.
     8225A random-number generator is an algorithm computing independent values.
     8226If the algorithm uses deterministic computation (predictable sequence of values), it generates \emph{pseudo} random numbers versus \emph{true} random numbers.
     8227
     8228All \newterm{pseudo random-number generators} (\newterm{PRNG}) involve some technique to scramble bits of a value, \eg multiplicative recurrence:
     8229\begin{cfa}
     8230rand = 36973 * (rand & 65535) + (rand >> 16); // scramble bits
     8231\end{cfa}
     8232Multiplication of large values adds new least-significant bits and drops most-significant bits.
     8233\begin{quote}
     8234\begin{tabular}{@{}r|l@{}}
     8235bits 63--32 (most)      & bits 31--0 (least)    \\
     8236\hline
     82370x0                                     & 0x3e8e36                              \\
     82380x5f                            & 0x718c25e1                    \\
     82390xad3e                          & 0x7b5f1dbe                    \\
     82400xbc3b                          & 0xac69ff19                    \\
     82410x1070f                         & 0x2d258dc6                    \\
     8242\end{tabular}
     8243\end{quote}
     8244By dropping bits 63--32, bits 31--0 become scrambled after each multiply.
     8245The least-significant bits \emph{appear} random but the same bits are always generated given a fixed starting value, called the \newterm{seed} (value 0x3e8e36 above).
     8246Hence, if a program uses the same seed, the same sequence of pseudo-random values is generated from the PRNG.
     8247Often the seed is set to another random value like a program's process identifier (©getpid©\index{getpid@©getpid©}) or time when the program is run;
     8248hence, one random value bootstraps another.
     8249Finally, a PRNG usually generates a range of large values, \eg ©[0, UINT_MAX]©, which are scaled using the modulus operator, \eg ©prng() % 5© produces random values in the range 0--4.
     8250
     8251\CFA provides a sequential and concurrent PRNGs.
     8252\begin{itemize}
     8253\item
     8254For sequential programs, like coroutining, the PRNG is used to randomize behaviour or values during execution, \eg in games, a character makes a random move or an object takes on a random value.
     8255\begin{cfa}
     8256struct PRNG { ... }; $\C[3.75in]{// opaque type}$
     8257void ?{}( PRNG & prng ); $\C{// random seed}$
     8258void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$
     8259void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$
     8260uint32_t get_seed( PRNG & prng ); $\C{// get seed}$
     8261uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$
     8262uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$
     8263uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$
     8264uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$
     8265\end{cfa}
     8266Sequential execution is repeatable given the same starting seeds for all ©PRNG©s.
     8267In this scenario, it is useful to have multiple ©PRNG©, \eg one per player or object so a type is provided to generate multiple instances.
     8268\VRef[Figure]{f:SequentialPRNG} shows an example that creates two sequential ©PRNG©s, sets both to the same seed (1009), and illustrates the three forms for generating random values, where both ©PRNG©s generate the same sequence of values.
     8269
     8270\begin{figure}
     8271\begin{cfa}
     8272PRNG prng1, prng2;
     8273®set_seed( prng1, 1009 )®;   ®set_seed( prng2, 1009 )®;
     8274for ( 10 ) {
     8275        // Do not cascade prng calls because side-effect functions called in arbitrary order.
     8276        sout | nlOff | ®prng( prng1 )®;  sout | ®prng( prng1, 5 )®;  sout | ®prng( prng1, 0, 5 )® | '\t';
     8277        sout | ®prng( prng2 )®;  sout | ®prng( prng2, 5 )®;  sout | ®prng( prng2, 0, 5 )® | nlOn;
     8278}
     8279\end{cfa}
     8280\begin{cquote}
     8281\begin{tabular}{@{}ll@{}}
     8282\begin{cfa}
     828337301721 2 2
     82841681308562 1 3
     8285290112364 3 2
     82861852700364 4 3
     8287733221210 1 3
     82881775396023 2 3
     8289123981445 2 3
     82902062557687 2 0
     8291283934808 1 0
     8292672325890 1 3
     8293\end{cfa}
     8294&
     8295\begin{cfa}
     829637301721 2 2
     82971681308562 1 3
     8298290112364 3 2
     82991852700364 4 3
     8300733221210 1 3
     83011775396023 2 3
     8302123981445 2 3
     83032062557687 2 0
     8304283934808 1 0
     8305672325890 1 3
     8306\end{cfa}
     8307\end{tabular}
     8308\end{cquote}
     8309\vspace{-10pt}
     8310\caption{Sequential PRNG}
     8311\label{f:SequentialPRNG}
     8312\end{figure}
     8313
     8314\item
     8315For concurrent programs, it is important the PRNG is thread-safe and not a point of contention.
     8316A PRNG in concurrent programs is often used to randomize execution in short-running programs, \eg ©yield( prng() % 5 )©.
     8317
     8318Because concurrent execution is non-deterministic, seeding the concurrent PRNG is less important, as repeatable execution is impossible.
     8319Hence, there is one system-wide PRNG (global seed) but each \CFA thread has its own non-contended PRNG state.
     8320If the global seed is set, threads start with this seed, until it is reset and than threads start with the reset seed.
     8321Hence, these threads generate the same sequence of random numbers from their specific starting seed.
     8322If the global seed is \emph{not} set, threads start with a random seed, until the global seed is set.
     8323Hence, these threads generate different sequences of random numbers.
     8324If each thread needs its own seed, use a sequential ©PRNG© in each thread.
     8325
     8326There are two versions of the PRNG functions to manipulate the thread-local PRNG-state, which are differentiated by performance.
     8327\begin{cfa}
     8328void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$
     8329uint32_t get_seed(); $\C{// get global seed}$
     8330// SLOWER
     8331uint32_t prng(); $\C{// [0,UINT\_MAX]}$
     8332uint32_t prng( uint32_t u ); $\C{// [0,u)}$
     8333uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$
     8334// FASTER
     8335uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th );     $\C{// [0,UINT\_MAX]}$
     8336uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$
     8337uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u );     $\C{// [l,u]}\CRT$
     8338\end{cfa}
     8339The slower ©prng© functions call ©active_thread© internally to access the thread-local PRNG-state, while the faster ©prng© functions are passed a pointer to the active thread.
     8340If the thread pointer is known, \eg in a thread ©main©, eliminating the call to ©active_thread© significantly reduces the cost for accessing the thread's PRNG state.
     8341\VRef[Figure]{f:ConcurrentPRNG} shows an example using the slower/faster concurrent PRNG in the program main and a thread.
     8342
     8343\begin{figure}
     8344\begin{cfa}
     8345thread T {};
     8346void main( ®T & th® ) {  // thread address
     8347        for ( i; 10 ) {
     8348                sout | nlOff | ®prng()®;  sout | ®prng( 5 )®;  sout | ®prng( 0, 5 )® | '\t';  // SLOWER
     8349                sout | nlOff | ®prng( th )®;  sout | ®prng( th, 5 )®;  sout | ®prng( th, 0, 5 )® | nlOn;  // FASTER
     8350        }
     8351}
     8352int main() {
     8353        set_seed( 1009 );
     8354        $\R{thread\LstStringStyle{\textdollar}}$ ®& th = *active_thread()®;  // program-main thread-address
     8355        for ( i; 10 ) {
     8356                sout | nlOff | ®prng()®; sout | ®prng( 5 )®; sout | ®prng( 0, 5 )® | '\t';  // SLOWER
     8357                sout | nlOff | ®prng( th )®; sout | ®prng( th, 5 )®; sout | ®prng( th, 0, 5 )® | nlOn;  // FASTER
     8358        }
     8359        sout | nl;
     8360        T t; // run thread
     8361}
     8362\end{cfa}
     8363\begin{cquote}
     8364\begin{tabular}{@{}ll@{}}
     8365\begin{cfa}
     836637301721 2 2
     8367290112364 3 2
     8368733221210 1 3
     8369123981445 2 3
     8370283934808 1 0
     83711414344101 1 3
     8372871831898 3 4
     83732142057611 4 4
     8374802117363 0 4
     83752346353643 1 3
     8376\end{cfa}
     8377&
     8378\begin{cfa}
     83791681308562 1 3
     83801852700364 4 3
     83811775396023 2 3
     83822062557687 2 0
     8383672325890 1 3
     8384873424536 3 4
     8385866783532 0 1
     838617310256 2 5
     8387492964499 0 0
     83882143013105 3 2
     8389\end{cfa}
     8390\end{tabular}
     8391\begin{cfa}
     8392// same output as above from thread t
     8393\end{cfa}
     8394\end{cquote}
     8395\caption{Concurrent PRNG}
     8396\label{f:ConcurrentPRNG}
     8397\end{figure}
     8398\end{itemize}
     8399
     8400
    81088401\section{Multi-precision Integers}
    81098402\label{s:MultiPrecisionIntegers}
     
    83108603\end{tabular}
    83118604\end{cquote}
    8312 \small
     8605
    83138606\begin{cfa}
    83148607Factorial Numbers
  • libcfa/src/Makefile.am

    ra556492 r9ef9644  
    7272        common.hfa \
    7373        fstream.hfa \
    74         heap.hfa \
    7574        iostream.hfa \
    7675        iterator.hfa \
     
    102101        startup.hfa \
    103102        virtual.c \
    104         virtual.h
     103        virtual.h \
     104        heap.cc \
     105        heap.h
    105106
    106107# not all platforms support concurrency, add option do disable it
     
    172173
    173174-include $(libdeps)
     175-include $(DEPDIR)/heap.Plo
    174176
    175177thread_libdeps = $(join \
  • libcfa/src/concurrency/coroutine.cfa

    ra556492 r9ef9644  
    8585// minimum feasible stack size in bytes
    8686static const size_t MinStackSize = 1000;
    87 extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
    88 extern int __map_prot;
     87
     88extern "C" {
     89        extern size_t __cfa_page_size;                          // architecture pagesize HACK, should go in proper runtime singleton
     90        extern int __map_prot;
     91}
    8992
    9093void __stack_prepare( __stack_info_t * this, size_t create_size );
     
    157160[void *, size_t] __stack_alloc( size_t storageSize ) {
    158161        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    159         assert(__page_size != 0l);
     162        assert(__cfa_page_size != 0l);
    160163        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
    161         size = ceiling(size, __page_size);
     164        size = ceiling(size, __cfa_page_size);
    162165
    163166        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
    164167        void * storage;
    165168        #if CFA_COROUTINE_USE_MMAP
    166                 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
     169                storage = mmap(0p, size + __cfa_page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    167170                if(storage == ((void*)-1)) {
    168171                        abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
    169172                }
    170                 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     173                if ( mprotect( storage, __cfa_page_size, PROT_NONE ) == -1 ) {
    171174                        abort( "coroutine stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    172175                } // if
    173                 storage = (void *)(((intptr_t)storage) + __page_size);
     176                storage = (void *)(((intptr_t)storage) + __cfa_page_size);
    174177        #else
    175178                __cfaabi_dbg_debug_do(
    176                         storage = memalign( __page_size, size + __page_size );
     179                        storage = memalign( __cfa_page_size, size + __cfa_page_size );
    177180                );
    178181                __cfaabi_dbg_no_debug_do(
     
    181184
    182185                __cfaabi_dbg_debug_do(
    183                         if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     186                        if ( mprotect( storage, __cfa_page_size, PROT_NONE ) == -1 ) {
    184187                                abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    185188                        }
    186                         storage = (void *)(((intptr_t)storage) + __page_size);
     189                        storage = (void *)(((intptr_t)storage) + __cfa_page_size);
    187190                );
    188191        #endif
     
    198201        #if CFA_COROUTINE_USE_MMAP
    199202                size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t);
    200                 storage = (void *)(((intptr_t)storage) - __page_size);
    201                 if(munmap(storage, size + __page_size) == -1) {
     203                storage = (void *)(((intptr_t)storage) - __cfa_page_size);
     204                if(munmap(storage, size + __cfa_page_size) == -1) {
    202205                        abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) );
    203206                }
    204207        #else
    205208                __cfaabi_dbg_debug_do(
    206                         storage = (char*)(storage) - __page_size;
    207                         if ( mprotect( storage, __page_size, __map_prot ) == -1 ) {
     209                        storage = (char*)(storage) - __cfa_page_size;
     210                        if ( mprotect( storage, __cfa_page_size, __map_prot ) == -1 ) {
    208211                                abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    209212                        }
  • libcfa/src/concurrency/kernel.hfa

    ra556492 r9ef9644  
    173173
    174174static inline void  ?{}(__timestamp_t & this) { this.tv = 0; this.ma = 0; }
    175 static inline void ^?{}(__timestamp_t & this) {}
     175static inline void ^?{}(__timestamp_t &) {}
    176176
    177177struct __attribute__((aligned(128))) __ready_queue_caches_t;
  • libcfa/src/concurrency/kernel/startup.cfa

    ra556492 r9ef9644  
    1818
    1919// C Includes
    20 #include <errno.h>              // errno
     20#include <errno.h>                                                                              // errno
    2121#include <signal.h>
    22 #include <string.h>             // strerror
    23 #include <unistd.h>             // sysconf
     22#include <string.h>                                                                             // strerror
     23#include <unistd.h>                                                                             // sysconf
    2424
    2525extern "C" {
    26       #include <limits.h>       // PTHREAD_STACK_MIN
    27         #include <unistd.h>       // syscall
    28         #include <sys/eventfd.h>  // eventfd
    29       #include <sys/mman.h>     // mprotect
    30       #include <sys/resource.h> // getrlimit
     26        #include <limits.h>                                                                     // PTHREAD_STACK_MIN
     27        #include <unistd.h>                                                                     // syscall
     28        #include <sys/eventfd.h>                                                        // eventfd
     29        #include <sys/mman.h>                                                           // mprotect
     30        #include <sys/resource.h>                                                       // getrlimit
    3131}
    3232
    3333// CFA Includes
    3434#include "kernel_private.hfa"
    35 #include "startup.hfa"          // STARTUP_PRIORITY_XXX
     35#include "startup.hfa"                                                                  // STARTUP_PRIORITY_XXX
    3636#include "limits.hfa"
    3737#include "math.hfa"
     
    102102extern void __wake_proc(processor *);
    103103extern int cfa_main_returned;                                                   // from interpose.cfa
    104 extern uint32_t __global_random_seed;
     104uint32_t __global_random_prime = 4_294_967_291u, __global_random_mask = false;
    105105
    106106//-----------------------------------------------------------------------------
     
    122122extern "C" {
    123123        struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    124 }
    125 
    126 extern size_t __page_size;
    127 extern int __map_prot;
     124        extern size_t __cfa_page_size;
     125        extern int __map_prot;
     126}
    128127
    129128//-----------------------------------------------------------------------------
     
    490489        preferred = ready_queue_new_preferred();
    491490        last_proc = 0p;
    492         random_state = __global_random_seed;
     491        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    493492        #if defined( __CFA_WITH_VERIFY__ )
    494493                canary = 0x0D15EA5E0D15EA5Ep;
     
    574573}
    575574
    576 extern size_t __page_size;
    577575void ^?{}(processor & this) with( this ){
    578576        /* paranoid */ verify( !__atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) );
     
    740738        void * stack;
    741739        #if CFA_PROCESSOR_USE_MMAP
    742                 stacksize = ceiling( stacksize, __page_size ) + __page_size;
     740                stacksize = ceiling( stacksize, __cfa_page_size ) + __cfa_page_size;
    743741                stack = mmap(0p, stacksize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
    744742                if(stack == ((void*)-1)) {
    745743                        abort( "pthread stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
    746744                }
    747                 if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     745                if ( mprotect( stack, __cfa_page_size, PROT_NONE ) == -1 ) {
    748746                        abort( "pthread stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    749747                } // if
    750748        #else
    751749                __cfaabi_dbg_debug_do(
    752                         stack = memalign( __page_size, stacksize + __page_size );
     750                        stack = memalign( __cfa_page_size, stacksize + __cfa_page_size );
    753751                        // pthread has no mechanism to create the guard page in user supplied stack.
    754                         if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     752                        if ( mprotect( stack, __cfa_page_size, PROT_NONE ) == -1 ) {
    755753                                abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    756754                        } // if
     
    779777                check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
    780778                assert( stacksize >= PTHREAD_STACK_MIN );
    781                 stacksize += __page_size;
     779                stacksize += __cfa_page_size;
    782780
    783781                if(munmap(stack, stacksize) == -1) {
     
    787785                __cfaabi_dbg_debug_do(
    788786                        // pthread has no mechanism to create the guard page in user supplied stack.
    789                         if ( mprotect( stack, __page_size, __map_prot ) == -1 ) {
     787                        if ( mprotect( stack, __cfa_page_size, __map_prot ) == -1 ) {
    790788                                abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    791789                        } // if
  • libcfa/src/concurrency/thread.cfa

    ra556492 r9ef9644  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jan 15 14:34:58 2022
    13 // Update Count     : 45
     12// Last Modified On : Sat Feb 12 15:24:18 2022
     13// Update Count     : 66
    1414//
    1515
     
    2525#include "invoke.h"
    2626
    27 extern uint32_t __global_random_seed;
     27extern uint32_t __global_random_seed, __global_random_prime, __global_random_mask;
    2828
    2929//-----------------------------------------------------------------------------
     
    4545        preferred = ready_queue_new_preferred();
    4646        last_proc = 0p;
    47         random_state = __global_random_seed;
     47        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    4848        #if defined( __CFA_WITH_VERIFY__ )
    4949                canary = 0x0D15EA5E0D15EA5Ep;
     
    176176
    177177void set_seed( uint32_t seed ) {
    178         active_thread()->random_state = __global_random_seed = seed;
    179         GENERATOR( active_thread()->random_state );
     178        uint32_t & state = active_thread()->random_state;
     179        state = __global_random_seed = seed;
     180        GENERATOR( state );
     181        __global_random_prime = state;
     182        __global_random_mask = true;
    180183} // set_seed
    181184
  • libcfa/src/concurrency/thread.hfa

    ra556492 r9ef9644  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  9 22:10:14 2022
    13 // Update Count     : 14
     12// Last Modified On : Fri Feb 11 16:34:07 2022
     13// Update Count     : 20
    1414//
    1515
     
    131131
    132132//----------
     133// prng
    133134static inline {
    134135        uint32_t prng( thread$ & th ) __attribute__(( warn_unused_result )) { return LCG( th.random_state ); } // [0,UINT_MAX]
    135136        uint32_t prng( thread$ & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
    136137        uint32_t prng( thread$ & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
    137 } // prng
     138        forall( T & | is_thread(T) ) {
     139                uint32_t prng( T & th ) __attribute__(( warn_unused_result )) { return prng( (thread &)th ); } // [0,UINT_MAX]
     140                uint32_t prng( T & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
     141                uint32_t prng( T & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
     142        } // distribution
     143} // distribution
    138144
    139145// Local Variables: //
  • libcfa/src/startup.cfa

    ra556492 r9ef9644  
    2727        void __cfaabi_appready_startup( void ) {
    2828                tzset();                                                                                // initialize time global variables
    29                 #ifdef __CFA_DEBUG__
     29                #ifdef __CFA_DEBUG__FIXME
    3030                extern void heapAppStart();
    3131                heapAppStart();
    32                 #endif // __CFA_DEBUG__
     32                #endif // __CFA_DEBUG__FIXME
    3333        } // __cfaabi_appready_startup
    3434
    3535        void __cfaabi_appready_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_APPREADY ) ));
    3636        void __cfaabi_appready_shutdown( void ) {
    37                 #ifdef __CFA_DEBUG__
     37                #ifdef __CFA_DEBUG__FIXME
    3838                extern void heapAppStop();
    3939                heapAppStop();
    40                 #endif // __CFA_DEBUG__
     40                #endif // __CFA_DEBUG__FIXME
    4141        } // __cfaabi_appready_shutdown
    4242
  • libcfa/src/stdhdr/malloc.h

    ra556492 r9ef9644  
    1818} // extern "C"
    1919
    20 #include <heap.hfa>
     20#include <heap.h>
    2121
    2222// Local Variables: //
  • libcfa/src/stdlib.hfa

    ra556492 r9ef9644  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 10 18:34:58 2022
    13 // Update Count     : 641
     12// Last Modified On : Sat Feb 12 17:22:25 2022
     13// Update Count     : 643
    1414//
    1515
     
    2121
    2222#include <stdlib.h>                                                                             // *alloc, strto*, ato*
    23 #include <heap.hfa>
     23#include <heap.h>
    2424
    2525
     
    209209
    210210        forall( TT... | { T * alloc_internal$( void *, T *, size_t, size_t, S_fill(T), TT ); } ) {
    211                 T * alloc_internal$( void *       , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
     211                T * alloc_internal$( void *       , T *        , size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {
    212212                return alloc_internal$( Resize, (T*)0p, Align, Dim, Fill, rest);
    213213                }
    214214
    215                 T * alloc_internal$( void * Resize, T *        , size_t Align, size_t Dim, S_fill(T) Fill, S_realloc(T) Realloc, TT rest) {
     215                T * alloc_internal$( void *        , T *        , size_t Align, size_t Dim, S_fill(T) Fill, S_realloc(T) Realloc, TT rest) {
    216216                return alloc_internal$( (void*)0p, Realloc, Align, Dim, Fill, rest);
    217217                }
     
    389389// Declaration :
    390390//   PRNG sprng = { 1009 } - set starting seed versus random seed
    391 //   
     391//
    392392// Interface :
    393393//   set_seed( sprng, 1009 ) - set starting seed for ALL kernel threads versus random seed
     
    412412void set_seed( PRNG & prng, uint32_t seed_ );
    413413static inline {
    414         void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); } // random seed
    415         void ?{}( PRNG & prng, uint32_t seed ) { set_seed( prng, seed ); } // fixed seed
     414        void ?{}( PRNG & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); } // random seed
     415        void ?{}( PRNG & prng, uint32_t seed ) with( prng ) { callcnt = 0; set_seed( prng, seed ); } // fixed seed
    416416        uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
    417417        uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return LCG( state ); } // [0,UINT_MAX]
  • src/AST/Convert.hpp

    ra556492 r9ef9644  
    2020class Declaration;
    2121namespace ast {
    22         struct TranslationUnit;
     22        class TranslationUnit;
    2323};
    2424
  • src/AST/Fwd.hpp

    ra556492 r9ef9644  
    140140typedef unsigned int UniqueId;
    141141
    142 struct TranslationUnit;
     142class TranslationUnit;
    143143// TODO: Get from the TranslationUnit:
    144144extern ptr<Type> sizeType;
  • src/AST/Pass.hpp

    ra556492 r9ef9644  
    239239private:
    240240
    241         // Regular nodes
     241        __pass::result1<ast::Stmt> call_accept( const ast::Stmt * );
     242        __pass::result1<ast::Expr> call_accept( const ast::Expr * );
     243
     244        /// This has a `type` member that is the return type for the
     245        /// generic call_accept if the generic call_accept is defined.
    242246        template< typename node_t >
    243         struct result1 {
    244                 bool differs;
    245                 const node_t * value;
    246 
    247                 template< typename object_t, typename super_t, typename field_t >
    248                 void apply(object_t *, field_t super_t::* field);
    249         };
    250 
    251         result1<ast::Stmt> call_accept( const ast::Stmt * );
    252         result1<ast::Expr> call_accept( const ast::Expr * );
     247        using generic_call_accept_result =
     248                std::enable_if<
     249                                !std::is_base_of<ast::Expr, node_t>::value &&
     250                                !std::is_base_of<ast::Stmt, node_t>::value
     251                        , __pass::result1<
     252                                typename std::remove_pointer< typename std::result_of<
     253                                        decltype(&node_t::accept)(node_t*, type&) >::type >::type
     254                        >
     255                >;
    253256
    254257        template< typename node_t >
    255258        auto call_accept( const node_t * node )
    256                 -> typename std::enable_if<
    257                                 !std::is_base_of<ast::Expr, node_t>::value &&
    258                                 !std::is_base_of<ast::Stmt, node_t>::value
    259                         , result1<
    260                                 typename std::remove_pointer< decltype( node->accept(*this) ) >::type
    261                         >
    262                 >::type;
     259                -> typename generic_call_accept_result<node_t>::type;
    263260
    264261        // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
    265         result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *);
    266 
    267         // Container of statements
     262        __pass::result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *);
     263
    268264        template< template <class...> class container_t >
    269         struct resultNstmt {
    270                 struct delta {
    271                         ptr<Stmt> nval;
    272                         ssize_t old_idx;
    273                         bool is_old;
    274 
    275                         delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {}
    276                 };
    277 
    278                 bool differs;
    279                 container_t< delta > values;
    280 
    281                 resultNstmt() : differs(false), values{} {}
    282                 resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {}
    283 
    284                 template< typename object_t, typename super_t, typename field_t >
    285                 void apply(object_t *, field_t super_t::* field);
    286 
    287                 template< template <class...> class incontainer_t >
    288                 void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) {
    289                         if(!stmts || stmts->empty()) return;
    290 
    291                         std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta {
    292                                         return delta( decl.release(), -1, false );
    293                                 });
    294                         stmts->clear();
    295                         differs = true;
    296                 }
    297 
    298                 template< template <class...> class incontainer_t >
    299                 void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) {
    300                         if(!decls || decls->empty()) return;
    301 
    302                         std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto {
    303                                         auto loc = decl->location;
    304                                         auto stmt = new DeclStmt( loc, decl.release() );
    305                                         return delta( stmt, -1, false );
    306                                 });
    307                         decls->clear();
    308                         differs = true;
    309                 }
    310         };
    311 
    312         template< template <class...> class container_t >
    313         resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & );
    314 
    315         // Container of something
     265        __pass::resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & );
     266
    316267        template< template <class...> class container_t, typename node_t >
    317         struct resultN {
    318                 bool differs;
    319                 container_t<ptr<node_t>> values;
    320 
    321                 template< typename object_t, typename super_t, typename field_t >
    322                 void apply(object_t *, field_t super_t::* field);
    323         };
    324 
    325         template< template <class...> class container_t, typename node_t >
    326         resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container );
     268        __pass::resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container );
    327269
    328270public:
  • src/AST/Pass.impl.hpp

    ra556492 r9ef9644  
    111111                }
    112112
    113 
    114113                //------------------------------
    115114                /// Check if value was mutated, different for pointers and containers
     
    125124        }
    126125
    127 
    128         template< typename core_t >
    129126        template< typename node_t >
    130127        template< typename object_t, typename super_t, typename field_t >
    131         void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) {
     128        void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {
    132129                object->*field = value;
    133130        }
     
    136133        template< typename node_t >
    137134        auto ast::Pass< core_t >::call_accept( const node_t * node )
    138                 -> typename std::enable_if<
    139                                 !std::is_base_of<ast::Expr, node_t>::value &&
    140                                 !std::is_base_of<ast::Stmt, node_t>::value
    141                         , ast::Pass< core_t >::result1<
    142                                 typename std::remove_pointer< decltype( node->accept(*this) ) >::type
    143                         >
    144                 >::type
     135                -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
    145136        {
    146137                __pedantic_pass_assert( __visit_children() );
     
    151142
    152143                auto nval = node->accept( *this );
    153                 ast::Pass< core_t >::result1<
     144                __pass::result1<
    154145                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
    155146                > res;
     
    160151
    161152        template< typename core_t >
    162         typename ast::Pass< core_t >::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     153        __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    163154                __pedantic_pass_assert( __visit_children() );
    164155                __pedantic_pass_assert( expr );
     
    174165
    175166        template< typename core_t >
    176         typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     167        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    177168                __pedantic_pass_assert( __visit_children() );
    178169                __pedantic_pass_assert( stmt );
     
    183174
    184175        template< typename core_t >
    185         typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     176        __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    186177                __pedantic_pass_assert( __visit_children() );
    187178                __pedantic_pass_assert( stmt );
     
    233224        }
    234225
    235         template< typename core_t >
    236226        template< template <class...> class container_t >
    237227        template< typename object_t, typename super_t, typename field_t >
    238         void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
     228        void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
    239229                auto & container = object->*field;
    240230                __pedantic_pass_assert( container.size() <= values.size() );
     
    243233
    244234                container_t<ptr<Stmt>> nvals;
    245                 for(delta & d : values) {
    246                         if( d.is_old ) {
     235                for (delta & d : values) {
     236                        if ( d.is_old ) {
    247237                                __pedantic_pass_assert( cit.idx <= d.old_idx );
    248238                                std::advance( cit, d.old_idx - cit.idx );
    249239                                nvals.push_back( std::move( (*cit).val) );
    250240                        } else {
    251                                 nvals.push_back( std::move(d.nval) );
     241                                nvals.push_back( std::move(d.new_val) );
    252242                        }
    253243                }
    254244
    255                 object->*field = std::move(nvals);
     245                container = std::move(nvals);
     246        }
     247
     248        template< template <class...> class container_t >
     249        template< template <class...> class incontainer_t >
     250        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {
     251                if (!stmts || stmts->empty()) return;
     252
     253                std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),
     254                        [](ast::ptr<ast::Stmt>& stmt) -> delta {
     255                                return delta( stmt.release(), -1, false );
     256                        });
     257                stmts->clear();
     258                differs = true;
     259        }
     260
     261        template< template<class...> class container_t >
     262        template< template<class...> class incontainer_t >
     263        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {
     264                if (!decls || decls->empty()) return;
     265
     266                std::transform(decls->begin(), decls->end(), std::back_inserter( values ),
     267                        [](ast::ptr<ast::Decl>& decl) -> delta {
     268                                auto loc = decl->location;
     269                                auto stmt = new DeclStmt( loc, decl.release() );
     270                                return delta( stmt, -1, false );
     271                        });
     272                decls->clear();
     273                differs = true;
    256274        }
    257275
    258276        template< typename core_t >
    259277        template< template <class...> class container_t >
    260         typename ast::Pass< core_t >::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     278        __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    261279                __pedantic_pass_assert( __visit_children() );
    262280                if( statements.empty() ) return {};
     
    285303                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    286304
    287                 resultNstmt<container_t> new_kids;
     305                __pass::resultNstmt<container_t> new_kids;
    288306                for( auto value : enumerate( statements ) ) {
    289307                        try {
     
    327345        }
    328346
    329         template< typename core_t >
    330347        template< template <class...> class container_t, typename node_t >
    331348        template< typename object_t, typename super_t, typename field_t >
    332         void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
     349        void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
    333350                auto & container = object->*field;
    334351                __pedantic_pass_assert( container.size() == values.size() );
     
    346363        template< typename core_t >
    347364        template< template <class...> class container_t, typename node_t >
    348         typename ast::Pass< core_t >::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     365        __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    349366                __pedantic_pass_assert( __visit_children() );
    350367                if( container.empty() ) return {};
     
    378395                if ( ! errors.isEmpty() ) { throw errors; }
    379396
    380                 return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated, new_kids };
     397                return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
    381398        }
    382399
  • src/AST/Pass.proto.hpp

    ra556492 r9ef9644  
    2323class Pass;
    2424
    25 struct TranslationUnit;
     25class TranslationUnit;
    2626
    2727struct PureVisitor;
     
    123123                static constexpr bool value = std::is_void< ret_t >::value ||
    124124                        std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
     125        };
     126
     127        /// The result is a single node.
     128        template< typename node_t >
     129        struct result1 {
     130                bool differs;
     131                const node_t * value;
     132
     133                template< typename object_t, typename super_t, typename field_t >
     134                void apply( object_t *, field_t super_t::* field );
     135        };
     136
     137        /// The result is a container of statements.
     138        template< template<class...> class container_t >
     139        struct resultNstmt {
     140                /// The delta/change on a single node.
     141                struct delta {
     142                        ptr<Stmt> new_val;
     143                        ssize_t old_idx;
     144                        bool is_old;
     145
     146                        delta(const Stmt * s, ssize_t i, bool old) :
     147                                new_val(s), old_idx(i), is_old(old) {}
     148                };
     149
     150                bool differs;
     151                container_t< delta > values;
     152
     153                template< typename object_t, typename super_t, typename field_t >
     154                void apply( object_t *, field_t super_t::* field );
     155
     156                template< template<class...> class incontainer_t >
     157                void take_all( incontainer_t<ptr<Stmt>> * stmts );
     158
     159                template< template<class...> class incontainer_t >
     160                void take_all( incontainer_t<ptr<Decl>> * decls );
     161        };
     162
     163        /// The result is a container of nodes.
     164        template< template<class...> class container_t, typename node_t >
     165        struct resultN {
     166                bool differs;
     167                container_t<ptr<node_t>> values;
     168
     169                template< typename object_t, typename super_t, typename field_t >
     170                void apply( object_t *, field_t super_t::* field );
    125171        };
    126172
  • src/AST/TranslationUnit.hpp

    ra556492 r9ef9644  
    2323namespace ast {
    2424
    25 struct TranslationUnit {
     25class TranslationUnit {
     26public:
    2627        std::list< ptr< Decl > > decls;
    2728
  • src/CodeGen/FixNames.h

    ra556492 r9ef9644  
    2020class Declaration;
    2121namespace ast {
    22         struct TranslationUnit;
     22        class TranslationUnit;
    2323}
    2424
  • src/Common/CodeLocation.h

    ra556492 r9ef9644  
    2525        /// Create a new unset CodeLocation.
    2626        CodeLocation() = default;
    27 
    2827
    2928        /// Create a new CodeLocation with the given values.
  • src/Common/CodeLocationTools.hpp

    ra556492 r9ef9644  
    1717
    1818namespace ast {
    19         struct TranslationUnit;
     19        class TranslationUnit;
    2020}
    2121
  • src/Common/ResolvProtoDump.hpp

    ra556492 r9ef9644  
    1717
    1818namespace ast {
    19         struct TranslationUnit;
     19        class TranslationUnit;
    2020}
    2121
  • src/Concurrency/Waitfor.cc

    ra556492 r9ef9644  
    372372                        ),
    373373                        new ListInit(
    374                                 map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
    375                                         Expression * init = new CastExpr(
    376                                                 new UntypedExpr(
    377                                                         new NameExpr( "get_monitor" ),
    378                                                         { expr }
    379                                                 ),
    380                                                 new PointerType(
    381                                                         noQualifiers,
    382                                                         new StructInstType(
    383                                                                 noQualifiers,
    384                                                                 decl_monitor
    385                                                         )
    386                                                 ),
    387                                                 false
    388                                         );
    389 
    390                                         ResolvExpr::findSingleExpression( init, indexer );
    391                                         return new SingleInit( init );
     374                                map_range < std::list<Initializer*> > ( clause.target.arguments, [](Expression * expr ){
     375                                        return new SingleInit( expr );
    392376                                })
    393377                        )
  • src/ControlStruct/MultiLevelExit.cpp

    ra556492 r9ef9644  
    176176        auto mutStmt = mutate( stmt );
    177177        // A child statement may set the break label.
    178         mutStmt->kids = move( fixBlock( stmt->kids, false ) );
     178        mutStmt->kids = fixBlock( stmt->kids, false );
    179179
    180180        if ( isLabeled ) {
  • src/InitTweak/FixInit.h

    ra556492 r9ef9644  
    2121class Declaration;
    2222namespace ast {
    23         struct TranslationUnit;
     23        class TranslationUnit;
    2424}
    2525
  • src/MakeLibCfa.h

    ra556492 r9ef9644  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // MakeLibCfa.h -- 
     7// MakeLibCfa.h --
    88//
    99// Author           : Richard C. Bilson
     
    2020class Declaration;
    2121namespace ast {
    22         struct TranslationUnit;
     22        class TranslationUnit;
    2323}
    2424
  • src/Parser/parser.yy

    ra556492 r9ef9644  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 11:06:13 2022
    13 // Update Count     : 5167
     12// Last Modified On : Fri Feb 11 14:26:15 2022
     13// Update Count     : 5174
    1414//
    1515
     
    11971197                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
    11981198        | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
    1199                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12001199                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
    12011200        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
     
    12041203                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    12051204        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1206                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12071205                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
    12081206        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
     
    12111209                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
    12121210        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1213                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12141211                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
    12151212        ;
     
    27292726        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    27302727                { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); }
     2728        | EXTERN STRINGliteral
     2729                {
     2730                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
     2731                        linkage = LinkageSpec::update( yylloc, linkage, $2 );
     2732                }
     2733          up external_definition down
     2734                {
     2735                        linkage = linkageStack.top();
     2736                        linkageStack.pop();
     2737                        $$ = $5;
     2738                }
    27312739        | EXTERN STRINGliteral                                                          // C++-style linkage specifier
    27322740                {
  • src/ResolvExpr/Resolver.cc

    ra556492 r9ef9644  
    11121112                }
    11131113
    1114                
     1114
    11151115        } // anonymous namespace
    11161116/// Establish post-resolver invariants for expressions
     
    11581158
    11591159        namespace {
    1160                
     1160
    11611161
    11621162                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     
    19051905
    19061906                        clause2.target.args.reserve( clause.target.args.size() );
     1907                        const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
    19071908                        for ( auto arg : argsCandidates.front() ) {
    1908                                 clause2.target.args.emplace_back( std::move( arg->expr ) );
     1909                                const auto & loc = stmt->location;
     1910
     1911                                ast::Expr * init = new ast::CastExpr( loc,
     1912                                        new ast::UntypedExpr( loc,
     1913                                                new ast::NameExpr( loc, "get_monitor" ),
     1914                                                { arg->expr }
     1915                                        ),
     1916                                        new ast::PointerType(
     1917                                                new ast::StructInstType(
     1918                                                        decl_monitor
     1919                                                )
     1920                                        )
     1921                                );
     1922
     1923                                clause2.target.args.emplace_back( findSingleExpression( init, symtab ) );
    19091924                        }
    19101925
     
    20772092                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
    20782093                        // xxx - can intrinsic gen ever fail?
    2079                         if (functionDecl->linkage == ast::Linkage::AutoGen) { 
     2094                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
    20802095                                auto mutDecl = mutate(functionDecl);
    20812096                                mutDecl->isDeleted = true;
  • src/ResolvExpr/Resolver.h

    ra556492 r9ef9644  
    3535        class StmtExpr;
    3636        class SymbolTable;
    37         struct TranslationUnit;
     37        class TranslationUnit;
    3838        class Type;
    3939        class TypeEnvironment;
     
    7272        ast::ptr< ast::Init > resolveCtorInit(
    7373                const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
    74         /// Resolves a statement expression 
     74        /// Resolves a statement expression
    7575        const ast::Expr * resolveStmtExpr(
    7676                const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
  • tests/PRNG.cfa

    ra556492 r9ef9644  
    88// Created On       : Wed Dec 29 09:38:12 2021
    99// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Fri Feb 11 08:16:43 2022
    11 // Update Count     : 328
     10// Last Modified On : Sat Feb 12 12:23:57 2022
     11// Update Count     : 342
    1212//
    1313
     
    2020#include <malloc.h>                                                                             // malloc_stats
    2121#include <locale.h>                                                                             // setlocale
     22#include <mutex_stmt.hfa>
    2223
    2324// FIX ME: spurious characters appear in output
     
    5051        } // for
    5152        double std = sqrt( sum / BUCKETS );
    52         sout | "trials"  | TRIALS | "buckets" | BUCKETS
    53                  | "min" | min | "max" | max
    54                  | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%";
     53        mutex( sout ) sout | "trials"  | TRIALS | "buckets" | BUCKETS
     54                | "min" | min | "max" | max
     55                | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%";
    5556} // avgstd
    5657
     58
    5759uint32_t seed = 1009;
    58 
    5960
    6061thread T1 {};
     
    9495        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
    9596        for ( TRIALS ) {
    96                 buckets[prng( (thread$ &)th ) % BUCKETS] += 1;  // concurrent
     97                buckets[prng( th ) % BUCKETS] += 1;     // concurrent
    9798        } // for
    9899        avgstd( buckets );
  • tests/meta/dumpable.cfa

    ra556492 r9ef9644  
    7272        }
    7373
    74         if((buf.f_bsize * buf.f_bavail) < 536870912) {
    75                 serr | "Available diskspace is less than ~500Mb: " | (buf.f_bsize * buf.f_bavail);
     74        uint64_t avail = buf.f_bavail;
     75        avail *= buf.f_bsize;
     76        if(avail < 536870912_l64u) {
     77                serr | "Available diskspace is less than ~500Mb: " | avail;
    7678        }
    7779
Note: See TracChangeset for help on using the changeset viewer.