Changes in / [9ef9644:a556492]
- Files:
-
- 2 added
- 4 deleted
- 31 edited
-
Jenkinsfile (modified) (1 diff)
-
benchmark/io/http/Makefile.am (modified) (1 diff)
-
benchmark/io/sendfile/consumer.c (deleted)
-
benchmark/io/sendfile/producer.c (deleted)
-
doc/user/user.tex (modified) (50 diffs)
-
libcfa/src/Makefile.am (modified) (3 diffs)
-
libcfa/src/concurrency/coroutine.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (8 diffs)
-
libcfa/src/concurrency/thread.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (2 diffs)
-
libcfa/src/heap.cc (deleted)
-
libcfa/src/heap.cfa (added)
-
libcfa/src/heap.h (deleted)
-
libcfa/src/heap.hfa (added)
-
libcfa/src/startup.cfa (modified) (1 diff)
-
libcfa/src/stdhdr/malloc.h (modified) (1 diff)
-
libcfa/src/stdlib.hfa (modified) (5 diffs)
-
src/AST/Convert.hpp (modified) (1 diff)
-
src/AST/Fwd.hpp (modified) (1 diff)
-
src/AST/Pass.hpp (modified) (1 diff)
-
src/AST/Pass.impl.hpp (modified) (13 diffs)
-
src/AST/Pass.proto.hpp (modified) (2 diffs)
-
src/AST/TranslationUnit.hpp (modified) (1 diff)
-
src/CodeGen/FixNames.h (modified) (1 diff)
-
src/Common/CodeLocation.h (modified) (1 diff)
-
src/Common/CodeLocationTools.hpp (modified) (1 diff)
-
src/Common/ResolvProtoDump.hpp (modified) (1 diff)
-
src/Concurrency/Waitfor.cc (modified) (1 diff)
-
src/ControlStruct/MultiLevelExit.cpp (modified) (1 diff)
-
src/InitTweak/FixInit.h (modified) (1 diff)
-
src/MakeLibCfa.h (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (5 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (4 diffs)
-
src/ResolvExpr/Resolver.h (modified) (2 diffs)
-
tests/PRNG.cfa (modified) (4 diffs)
-
tests/meta/dumpable.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
r9ef9644 ra556492 161 161 Tools.BuildStage('Test: full', Settings.RunAllTests) { 162 162 dir (BuildDir) { 163 jopt = ""164 if( Settings.Architecture.node == 'x86' ) {165 jopt = "-j2"166 }167 163 //Run the tests from the tests directory 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"""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""" 170 166 } 171 167 } -
benchmark/io/http/Makefile.am
r9ef9644 ra556492 50 50 .dummy_hackxx.cpp: 51 51 @echo "int bar() { return 0; }" > ${@} 52 53 # add dependency of cfa files54 nodist_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 languages58 nodist_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 65 list_libdeps:66 echo "objects: " $(nodist_httpforall_OBJECTS)67 echo "depends: " $(nodist_httpforall_DEPENDS) -
doc/user/user.tex
r9ef9644 ra556492 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : S at Feb 12 17:04:03 202214 %% Update Count : 5 37613 %% Last Modified On : Sun Oct 10 12:45:00 2021 14 %% Update Count : 5095 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 17 17 % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended 18 18 19 \documentclass[twoside ]{article}19 \documentclass[twoside,11pt]{article} 20 20 21 21 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 40 40 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_ 41 41 % 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-' 43 43 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 44 44 % math escape $...$ (dollar symbol) … … 85 85 \newcommand{\B}[1]{{\Textbf[blue]{#1}}} 86 86 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} 87 \newcommand{\Sp}{\R{\textvisiblespace}}88 87 \newcommand{\KWC}{K-W C\xspace} 89 88 … … 157 156 One 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''. 158 157 Programmers can cautiously add \CFA extensions to their C programs in any order and at any time to incrementally move towards safer, higher-level programming. 159 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 the irC counterpart.160 There is no notion or requirement for \emph{rewriting} a legacy C program to\CFA;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; 161 160 instead, a programmer evolves a legacy program into \CFA by incrementally incorporating \CFA features. 162 161 As well, new programs can be written in \CFA using a combination of C and \CFA features. … … 164 163 165 164 \Index*[C++]{\CC{}}~\cite{c++:v1} had a similar goal 30 years ago, allowing object-oriented programming to be incrementally added to C. 166 However, \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.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. 167 166 In contrast, \CFA has 30 years of hindsight and a clean starting point. 168 167 169 168 Like \Index*[C++]{\CC{}}, there may be both old and new ways to achieve the same effect. 170 169 For example, the following programs compare the C, \CFA, and \CC I/O mechanisms, where the programs output the same result. 171 \begin{ flushleft}170 \begin{center} 172 171 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 173 \multicolumn{1}{ @{}c@{\hspace{1em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}} \\174 \begin{cfa} [tabsize=3]172 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 173 \begin{cfa} 175 174 #include <stdio.h>$\indexc{stdio.h}$ 176 175 … … 181 180 \end{cfa} 182 181 & 183 \begin{cfa} [tabsize=3]182 \begin{cfa} 184 183 #include <fstream>$\indexc{fstream}$ 185 184 … … 190 189 \end{cfa} 191 190 & 192 \begin{cfa} [tabsize=3]191 \begin{cfa} 193 192 #include <iostream>$\indexc{iostream}$ 194 193 using namespace std; 195 194 int main() { 196 195 int x = 0, y = 1, z = 2; 197 ®cout << x << ' ' << y << ' ' << z <<endl;®196 ®cout<<x<<" "<<y<<" "<<z<<endl;® 198 197 } 199 198 \end{cfa} 200 199 \end{tabular} 201 \end{ flushleft}200 \end{center} 202 201 While \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}. 203 202 … … 239 238 however, it largely extended the C language, and did not address many of C's existing problems.\footnote{% 240 239 Two 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.} 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.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. 242 241 \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. 243 242 These 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. … … 334 333 long double _Complex ®abs®( long double _Complex ); 335 334 \end{cfa} 336 The 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).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). 337 336 Overloaded names must use \newterm{name mangling}\index{mangling!name} to create unique names that are different from unmangled C names. 338 337 Hence, 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. … … 378 377 The program is linked with the debugging version of the runtime system. 379 378 The debug version performs runtime checks to aid the debugging phase of a \CFA program, but can substantially slow program execution. 380 The runtime checks should only be removed after aprogram is completely debugged.379 The runtime checks should only be removed after the program is completely debugged. 381 380 \textbf{This option is the default.} 382 381 … … 453 452 cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude 454 453 \end{lstlisting} 455 Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces.456 \begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}]457 cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude458 \end{lstlisting}459 454 \begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt] 460 455 \item … … 538 533 double ®``®forall = 3.5; 539 534 \end{cfa} 540 Existing 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. 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. 541 537 \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©. 542 538 Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience. … … 631 627 \subsection{\texorpdfstring{\LstKeywordStyle{if} / \LstKeywordStyle{while} Statement}{if / while Statement}} 632 628 633 The \Indexc{if}/\Indexc{while} expression allows declarations, similar to \Indexc{for}declaration expression.\footnote{634 Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.}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.} 635 631 \begin{cfa} 636 632 if ( ®int x = f()® ) ... $\C{// x != 0}$ … … 644 640 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$ 645 641 \end{cfa} 646 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 \Indexc{&&}operator.647 The 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©.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. 648 644 \CC only provides a single declaration always compared ©!=© to 0. 649 645 … … 653 649 \label{s:caseClause} 654 650 655 C restricts the \Indexc{case} clause of a \Indexc{switch}statement to a single value.651 C restricts the ©case© clause of a ©switch© statement to a single value. 656 652 For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values. 657 Requiring a ©case© clause for each value is notin the spirit of brevity normally associated with C.658 Therefore, the ©case© clause is extended with a list of 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: 659 655 \begin{cquote} 660 656 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} … … 707 703 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 708 704 709 C allows a number of questionable forms for the \Indexc{switch}statement:705 C allows a number of questionable forms for the ©switch© statement: 710 706 \begin{enumerate} 711 707 \item 712 By default, the end of a \Indexc{case}clause\footnote{708 By default, the end of a ©case© clause\footnote{ 713 709 In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.} 714 710 \emph{falls through} to the next ©case© clause in the ©switch© statement; 715 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly \Indexc{break}:711 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©: 716 712 \begin{cfa} 717 713 switch ( i ) { 718 714 case 1: 719 715 ... 720 $\R{\LstCommentStyle{// fall-through}}$716 // fall-through 721 717 case 2: 722 718 ... 723 ®break;®// exit switch statement719 break; // exit switch statement 724 720 } 725 721 \end{cfa} … … 767 763 } 768 764 \end{cfa} 769 This situation is better handled bya list of case values \see{\VRef{s:caseClause}}.765 This situation better handled without fall-through by allowing a list of case values \see{\VRef{s:caseClause}}. 770 766 While 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. 771 767 Hence, 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. … … 781 777 ... 782 778 } // if 779 case 2: 780 while ( j < 5 ) { 781 ... 782 ®case 3:® // transfer into "while" statement 783 ... 784 } // while 785 } // switch 783 786 \end{cfa} 784 787 This usage branches into control structures, which is known to cause both comprehension and technical difficulties. … … 786 789 The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning. 787 790 There are few arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it. 788 789 This C idiom is known as ``\Index*{Duff's device}''~\cite{Duff83}, from this example: 791 Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}: 790 792 \begin{cfa} 791 793 register int n = (count + 7) / 8; … … 856 858 still works. 857 859 Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments. 858 Therefore, 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: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: 859 861 \begin{cfa} 860 862 ®choose® ( i ) { … … 883 885 Therefore, no change is made for this issue. 884 886 \item 885 Dealing 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{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{ 886 888 Essentially, 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. 887 889 Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound. … … 906 908 \subsection{Non-terminating and Labelled \texorpdfstring{\LstKeywordStyle{fallthrough}}{Non-terminating and Labelled fallthrough}} 907 909 908 The \Indexc{fallthrough} clause may be non-terminating within a \Indexc{case}clause or have a target label to common code from multiple case clauses.910 The ©fallthrough© clause may be non-terminating within a ©case© clause or have a target label to common code from multiple case clauses. 909 911 \begin{center} 910 912 \begin{tabular}{@{}lll@{}} … … 958 960 \end{tabular} 959 961 \end{center} 960 The target label must be below the \Indexc{fallthrough}and may not be nested in a control structure, and961 the target label must be at the same or higher level as the containing \Indexc{case}clause and located at962 the same level as a ©case© clause; the target label may be case \Indexc{default}, but only associated963 with the current \Indexc{switch}/\Indexc{choose}statement.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. 964 966 965 967 \begin{figure} … … 1074 1076 Looping a fixed number of times, possibly with a loop index, occurs frequently. 1075 1077 \CFA condenses simply looping to facilitate coding speed and safety. 1076 The \Indexc{for}, \Indexc{while}, and \Indexc{do}loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}:1078 The ©for©/©while©/©do-while© loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}: 1077 1079 \begin{itemize}[itemsep=0pt] 1078 1080 \item … … 1143 1145 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} 1144 1146 1145 C \Indexc{continue} and \Indexc{break}statements, for altering control flow, are restricted to one level of nesting for a particular control structure.1147 C ©continue© and ©break© statements, for altering control flow, are restricted to one level of nesting for a particular control structure. 1146 1148 This restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting. 1147 1149 To 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. 1148 For both ©continue© and ©break©, the target label must be directly associated with a \Indexc{for}, \Indexc{while} or \Indexc{do}statement;1149 for ©break©, the target label can also be associated with a \Indexc{switch}, \Indexc{if}or compound (©{}©) statement.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. 1150 1152 \VRef[Figure]{f:MultiLevelExit} shows a comparison between labelled ©continue© and ©break© and the corresponding C equivalent using ©goto© and labels. 1151 1153 The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s. … … 1222 1224 \end{figure} 1223 1225 1224 Both labelled \Indexc{continue} and \Indexc{break} are a \Indexc{goto}\index{goto@©goto©!restricted} restricted in the following ways:1226 Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways: 1225 1227 \begin{itemize} 1226 1228 \item … … 1238 1240 1239 1241 1240 \subsection{\texorpdfstring{Extended \LstKeywordStyle{else}}{Extended else}}1241 \label{s:ExtendedElse}1242 \index{extended ©else©}1243 1244 The ©if© statement has an optional ©else© clause executed if the conditional is false.1245 This concept is extended to the \Indexc{while}, \Indexc{for}, and \Indexc{do} looping constructs (like Python).1246 Hence, if the loop conditional becomes false, looping stops and the corresponding ©else© clause is executed, if present.1247 1248 The 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}1251 int a[10];1252 \end{cfa}1253 \begin{tabular}{@{}lll@{}}1254 \begin{cfa}1255 1256 while ( int i = 0; i < 10 ) {1257 if ( a[i] == 3 ) break; // found1258 i += 1;1259 } ®else® { // i == 101260 sout | "not found";1261 }1262 \end{cfa}1263 &1264 \begin{cfa}1265 1266 for ( i; 10 ) {1267 if ( a[i] == 3 ) break; // found1268 1269 } ®else® { // i == 101270 sout | "not found";1271 }1272 \end{cfa}1273 &1274 \begin{cfa}1275 int i = 0;1276 do {1277 if ( a[i] == 3 ) break; // found1278 i += 1;1279 } while( i < 10 ) ®else® { // i == 101280 sout | "not found";1281 }1282 \end{cfa}1283 \end{tabular}1284 \end{cquote}1285 Note, \Index{dangling else} now occurs with \Indexc{if}, \Indexc{while}, \Indexc{for}, \Indexc{do}, and \Indexc{waitfor}.1286 1287 1288 1242 %\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}} 1289 1243 \subsection{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}} … … 1312 1266 Therefore, reducing aggregate qualification is a useful language design goal. 1313 1267 1314 C partially addresses the problem by eliminating qualification for enumerated types and unnamed \emph{nested} aggregates, whichopen their scope into the containing aggregate.1268 C allows unnamed nested aggregates that open their scope into the containing aggregate. 1315 1269 This feature is used to group fields for attributes and/or with ©union© aggregates. 1316 1270 \begin{cfa} 1317 1271 struct S { 1318 struct $\R{\LstCommentStyle{/* unnamed */}}${ int g, h; } __attribute__(( aligned(64) ));1272 struct { int g, h; } __attribute__(( aligned(64) )); 1319 1273 int tag; 1320 union $\R{\LstCommentStyle{/* unnamed */}}${1274 union { 1321 1275 struct { char c1, c2; } __attribute__(( aligned(128) )); 1322 1276 struct { int i1, i2; }; 1323 1277 struct { double d1, d2; }; 1324 1278 }; 1325 } s; 1326 enum { R, G, B }; 1327 s.g; s.h; s.tag = R; s.c1; s.c2; s.i1 = G; s.i2 = B; s.d1; s.d2; 1279 }; 1280 s.g; s.h; s.tag; s.c1; s.c2; s.i1; s.i2; s.d1; s.d2; 1328 1281 \end{cfa} 1329 1282 … … 1370 1323 \end{cfa} 1371 1324 where qualification is only necessary to disambiguate the shadowed variable ©i©. 1372 In detail, the ©with© statement may form a function body or be nested within a function body. 1373 1325 1326 In detail, the ©with© statement may appear as the body of a function or nested within a function body. 1374 1327 The ©with© clause takes a list of expressions, where each expression provides an aggregate type and object. 1375 1328 (Enumerations are already opened.) … … 1380 1333 \end{cfa} 1381 1334 The expression object is the implicit qualifier for the open structure-fields. 1382 1383 1335 \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. 1384 1336 All expressions in the expression list are open in parallel within the compound statement. … … 1410 1362 \end{cfa} 1411 1363 A cast or qualification can be used to disambiguate variables within a ©with© \emph{statement}. 1412 A cast can alsobe used to disambiguate among overload variables in a ©with© \emph{expression}:1364 A cast can be used to disambiguate among overload variables in a ©with© \emph{expression}: 1413 1365 \begin{cfa} 1414 1366 with ( w ) { ... } $\C{// ambiguous, same name and no context}$ … … 1419 1371 Finally, there is an interesting problem between parameters and the function-body ©with©, \eg: 1420 1372 \begin{cfa} 1421 void f( S & s, char c ) with ( s ) { 1422 ®s.c = c;® i = 3; d = 5.5; $\C{// initialize fields}$ 1423 } 1424 \end{cfa} 1425 Here, 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©. 1426 To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate: 1427 \begin{cfa} 1428 struct Params { $\C{// s explicitly opened so S \& s elided}$ 1429 char c; 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; 1430 1383 } params; 1431 1384 \end{cfa} 1432 1385 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1433 1386 \begin{cfa} 1434 void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only1435 s. c = ®c;® i = 3; d= 5.5;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; 1436 1389 } 1437 1390 \end{cfa} 1438 1391 This implicit semantic matches with programmer expectation. 1392 1439 1393 1440 1394 … … 3443 3397 This requirement is the same as for comma expressions in argument lists. 3444 3398 3445 Type qualifiers, \ie ©const© and ©volatile©, may modify a tuple type.3446 The meaning is t o distribute the qualifieracross all of the types in the tuple, \eg: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: 3447 3401 \begin{cfa} 3448 3402 const volatile [ int, float, const int ] x; … … 3643 3597 Stream ©exit© implicitly returns ©EXIT_FAILURE© to the shell. 3644 3598 \begin{cfa} 3645 ®exit® | "x (" | x | ") negative value."; // terminate and return EXIT_FAILURE to shell3646 ®abort® | "x (" | x | ") negative value."; // terminate and generate stack trace and core file3599 ®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 3647 3601 \end{cfa} 3648 3602 Note, \CFA stream variables ©stdin©, ©stdout©, ©stderr©, ©exit©, and ©abort© overload C variables ©stdin©, ©stdout©, ©stderr©, and functions ©exit© and ©abort©, respectively. … … 4313 4267 sout | '1' | '2' | '3'; 4314 4268 sout | 1 | "" | 2 | "" | 3; 4315 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x Â¥"4316 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;4269 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥" 4270 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10; 4317 4271 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" 4318 | 7 | " ¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";4272 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x"; 4319 4273 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; 4320 4274 sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4; … … 4492 4446 The 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: 4493 4447 \begin{cfa} 4494 $\emph{thread\(_1\)}$ : ®mutex( sout)® sout | "abc " | "def ";4495 $\emph{thread\(_2\)}$ : ®mutex( sout)® sout | "uvw " | "xyz ";4448 $\emph{thread\(_1\)}$ : ®mutex()® sout | "abc " | "def "; 4449 $\emph{thread\(_2\)}$ : ®mutex()® sout | "uvw " | "xyz "; 4496 4450 \end{cfa} 4497 4451 Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order. … … 4516 4470 ®mutex( sout )® { 4517 4471 sout | 1; 4518 ®mutex( sout) sout® | 2 | 3; $\C{// unnecessary, but ok because of recursive lock}$4472 ®mutex() sout® | 2 | 3; $\C{// unnecessary, but ok because of recursive lock}$ 4519 4473 sout | 4; 4520 4474 } // implicitly release sout lock … … 4528 4482 int x, y, z, w; 4529 4483 sin | x; 4530 ®mutex( sin )® sin | y | z;$\C{// unnecessary, but ok because of recursive lock}$4484 ®mutex() sin® | y | z; $\C{// unnecessary, but ok because of recursive lock}$ 4531 4485 sin | w; 4532 4486 } // implicitly release sin lock … … 4537 4491 \Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg: 4538 4492 \begin{cfa} 4539 ®mutex( sout )® sout| "data:" | rtn( mon ); $\C{// mutex call on monitor}$4493 ®mutex() sout® | "data:" | rtn( mon ); $\C{// mutex call on monitor}$ 4540 4494 \end{cfa} 4541 4495 If 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. … … 4544 4498 \begin{cfa} 4545 4499 int ®data® = rtn( mon ); 4546 mutex( sout ) sout | "data:" | ®data®; 4547 \end{cfa} 4548 4549 4550 \subsection{Locale} 4551 \index{stream!locale} 4552 \index{locale!stream} 4553 4554 Cultures use different syntax, called a \newterm{locale}, for printing numbers so they are easier to read, \eg: 4555 \begin{cfa} 4556 12®,®345®.®123 $\C[1.25in]{// comma separator, period decimal-point}$ 4557 12®.®345®,®123 $\C{// period separator, comma decimal-point}$ 4558 12$\Sp$345®,®123®.® $\C{// space separator, comma decimal-point, period terminator}\CRT$ 4559 \end{cfa} 4560 A 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. 4562 Furthermore, a locale covers the syntax for many cultural items, \eg address, measurement, money, etc. 4563 This 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 4572 int 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 4590 Default locale off 4591 12 123 1234 12345 123456 1234567 4592 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345 4593 4594 Locale on en_US.UTF-8 4595 12 123 1®,®234 12®,®345 123®,®456 1®,®234®,®567 4596 12®.® 123®.®1 1®,®234®.®12 12®,®345®.®123 123®,®456®.®1234 1®,®234®,®567®.®12345 4597 4598 German de_DE.UTF-8 4599 12 123 1®.®234 12®.®345 123®.®456 1®.®234®.®567 4600 12®.® 123®,®1®.® 1®.®234®,®12 12®.®345®,®123 123®.®456®,®1234 1®.®234®.®567®,®12345 4601 4602 Ukraine uk_UA.utf8 4603 12 123 1 234 12 345 123 456 1 234 567 4604 12®.® 123®,®1®.® 1$\Sp$234®,®12®.® 12$\Sp$ 345®,®123®.® 123$\Sp$ 456®,®1234®.® 1$\Sp$ 234$\Sp$567®,®12345®.® 4605 4606 Default locale off C 4607 12 123 1234 12345 123456 1234567 4608 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345 4609 \end{cfa} 4610 \caption{Stream Locale} 4611 \label{f:StreamLocale} 4612 \end{figure} 4500 mutex() sout | "data:" | ®data®; 4501 \end{cfa} 4613 4502 4614 4503 … … 4666 4555 \end{figure} 4667 4556 4668 4669 4557 \begin{comment} 4670 4558 \section{Types} … … 4749 4637 4750 4638 4751 \s ection{Structures}4639 \subsection{Structures} 4752 4640 4753 4641 Structures in \CFA are basically the same as structures in C. … … 5382 5270 \subsection{Coroutine} 5383 5271 5384 \Index{Coroutines} are the precursor to t hreads.5272 \Index{Coroutines} are the precursor to tasks. 5385 5273 \VRef[Figure]{f:FibonacciCoroutine} shows a coroutine that computes the \Index*{Fibonacci} numbers. 5386 5274 … … 5484 5372 5485 5373 5486 \subsection{T hreads}5374 \subsection{Tasks} 5487 5375 5488 5376 \CFA also provides a simple mechanism for creating and utilizing user level threads. 5489 A t hreadprovides mutual exclusion like a monitor, and also has its own execution state and a thread of control.5490 Similar to a monitor, a t hreadis defined like a structure: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: 5491 5379 5492 5380 \begin{figure} … … 5532 5420 } 5533 5421 \end{cfa} 5534 \caption{Simple T hreads}5535 \label{f:SimpleT hreads}5422 \caption{Simple Tasks} 5423 \label{f:SimpleTasks} 5536 5424 \end{figure} 5537 5425 … … 6900 6788 In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as: 6901 6789 \begin{cfa} 6902 *?$\ Sp$*? $\C{// dereference operator, dereference operator}$6903 *$\ Sp$?*? $\C{// dereference, multiplication operator}$6790 *?$\R{\textvisiblespace}$*? $\C{// dereference operator, dereference operator}$ 6791 *$\R{\textvisiblespace}$?*? $\C{// dereference, multiplication operator}$ 6904 6792 \end{cfa} 6905 6793 By default, the first interpretation is selected, which does not yield a meaningful parse. … … 6925 6813 Therefore, it is necessary to disambiguate these cases with a space: 6926 6814 \begin{cfa} 6927 i++$\ Sp$? i : 0;6928 i?$\ Sp$++i : 0;6815 i++$\R{\textvisiblespace}$? i : 0; 6816 i?$\R{\textvisiblespace}$++i : 0; 6929 6817 \end{cfa} 6930 6818 … … 7542 7430 char random( void );$\indexc{random}$ 7543 7431 char random( char u ); $\C{// [0,u)}$ 7544 char random( char l, char u ); $\C{// [l,u ]}$7432 char random( char l, char u ); $\C{// [l,u)}$ 7545 7433 int random( void ); 7546 7434 int random( int u ); $\C{// [0,u)}$ 7547 int random( int l, int u ); $\C{// [l,u ]}$7435 int random( int l, int u ); $\C{// [l,u)}$ 7548 7436 unsigned int random( void ); 7549 7437 unsigned int random( unsigned int u ); $\C{// [0,u)}$ 7550 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u ]}$7438 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u)}$ 7551 7439 long int random( void ); 7552 7440 long int random( long int u ); $\C{// [0,u)}$ 7553 long int random( long int l, long int u ); $\C{// [l,u ]}$7441 long int random( long int l, long int u ); $\C{// [l,u)}$ 7554 7442 unsigned long int random( void ); 7555 7443 unsigned long int random( unsigned long int u ); $\C{// [0,u)}$ 7556 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u ]}$7444 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u)}$ 7557 7445 float random( void ); $\C{// [0.0, 1.0)}$ 7558 7446 double random( void ); $\C{// [0.0, 1.0)}$ … … 8218 8106 8219 8107 8220 \section{Pseudo Random Number Generator}8221 \label{s:PRNG}8222 8223 Random 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.8224 While a primary goal of programming is computing values that are \emph{not} random, random values are useful in simulation, cryptography, games, etc.8225 A random-number generator is an algorithm computing independent values.8226 If the algorithm uses deterministic computation (predictable sequence of values), it generates \emph{pseudo} random numbers versus \emph{true} random numbers.8227 8228 All \newterm{pseudo random-number generators} (\newterm{PRNG}) involve some technique to scramble bits of a value, \eg multiplicative recurrence:8229 \begin{cfa}8230 rand = 36973 * (rand & 65535) + (rand >> 16); // scramble bits8231 \end{cfa}8232 Multiplication of large values adds new least-significant bits and drops most-significant bits.8233 \begin{quote}8234 \begin{tabular}{@{}r|l@{}}8235 bits 63--32 (most) & bits 31--0 (least) \\8236 \hline8237 0x0 & 0x3e8e36 \\8238 0x5f & 0x718c25e1 \\8239 0xad3e & 0x7b5f1dbe \\8240 0xbc3b & 0xac69ff19 \\8241 0x1070f & 0x2d258dc6 \\8242 \end{tabular}8243 \end{quote}8244 By dropping bits 63--32, bits 31--0 become scrambled after each multiply.8245 The 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).8246 Hence, if a program uses the same seed, the same sequence of pseudo-random values is generated from the PRNG.8247 Often 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;8248 hence, one random value bootstraps another.8249 Finally, 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 \item8254 For 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}8256 struct PRNG { ... }; $\C[3.75in]{// opaque type}$8257 void ?{}( PRNG & prng ); $\C{// random seed}$8258 void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$8259 void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$8260 uint32_t get_seed( PRNG & prng ); $\C{// get seed}$8261 uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$8262 uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$8263 uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$8264 uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$8265 \end{cfa}8266 Sequential execution is repeatable given the same starting seeds for all ©PRNG©s.8267 In 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}8272 PRNG prng1, prng2;8273 ®set_seed( prng1, 1009 )®; ®set_seed( prng2, 1009 )®;8274 for ( 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}8283 37301721 2 28284 1681308562 1 38285 290112364 3 28286 1852700364 4 38287 733221210 1 38288 1775396023 2 38289 123981445 2 38290 2062557687 2 08291 283934808 1 08292 672325890 1 38293 \end{cfa}8294 &8295 \begin{cfa}8296 37301721 2 28297 1681308562 1 38298 290112364 3 28299 1852700364 4 38300 733221210 1 38301 1775396023 2 38302 123981445 2 38303 2062557687 2 08304 283934808 1 08305 672325890 1 38306 \end{cfa}8307 \end{tabular}8308 \end{cquote}8309 \vspace{-10pt}8310 \caption{Sequential PRNG}8311 \label{f:SequentialPRNG}8312 \end{figure}8313 8314 \item8315 For concurrent programs, it is important the PRNG is thread-safe and not a point of contention.8316 A PRNG in concurrent programs is often used to randomize execution in short-running programs, \eg ©yield( prng() % 5 )©.8317 8318 Because concurrent execution is non-deterministic, seeding the concurrent PRNG is less important, as repeatable execution is impossible.8319 Hence, there is one system-wide PRNG (global seed) but each \CFA thread has its own non-contended PRNG state.8320 If the global seed is set, threads start with this seed, until it is reset and than threads start with the reset seed.8321 Hence, these threads generate the same sequence of random numbers from their specific starting seed.8322 If the global seed is \emph{not} set, threads start with a random seed, until the global seed is set.8323 Hence, these threads generate different sequences of random numbers.8324 If each thread needs its own seed, use a sequential ©PRNG© in each thread.8325 8326 There are two versions of the PRNG functions to manipulate the thread-local PRNG-state, which are differentiated by performance.8327 \begin{cfa}8328 void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$8329 uint32_t get_seed(); $\C{// get global seed}$8330 // SLOWER8331 uint32_t prng(); $\C{// [0,UINT\_MAX]}$8332 uint32_t prng( uint32_t u ); $\C{// [0,u)}$8333 uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$8334 // FASTER8335 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th ); $\C{// [0,UINT\_MAX]}$8336 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$8337 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u ); $\C{// [l,u]}\CRT$8338 \end{cfa}8339 The 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.8340 If 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}8345 thread T {};8346 void main( ®T & th® ) { // thread address8347 for ( i; 10 ) {8348 sout | nlOff | ®prng()®; sout | ®prng( 5 )®; sout | ®prng( 0, 5 )® | '\t'; // SLOWER8349 sout | nlOff | ®prng( th )®; sout | ®prng( th, 5 )®; sout | ®prng( th, 0, 5 )® | nlOn; // FASTER8350 }8351 }8352 int main() {8353 set_seed( 1009 );8354 $\R{thread\LstStringStyle{\textdollar}}$ ®& th = *active_thread()®; // program-main thread-address8355 for ( i; 10 ) {8356 sout | nlOff | ®prng()®; sout | ®prng( 5 )®; sout | ®prng( 0, 5 )® | '\t'; // SLOWER8357 sout | nlOff | ®prng( th )®; sout | ®prng( th, 5 )®; sout | ®prng( th, 0, 5 )® | nlOn; // FASTER8358 }8359 sout | nl;8360 T t; // run thread8361 }8362 \end{cfa}8363 \begin{cquote}8364 \begin{tabular}{@{}ll@{}}8365 \begin{cfa}8366 37301721 2 28367 290112364 3 28368 733221210 1 38369 123981445 2 38370 283934808 1 08371 1414344101 1 38372 871831898 3 48373 2142057611 4 48374 802117363 0 48375 2346353643 1 38376 \end{cfa}8377 &8378 \begin{cfa}8379 1681308562 1 38380 1852700364 4 38381 1775396023 2 38382 2062557687 2 08383 672325890 1 38384 873424536 3 48385 866783532 0 18386 17310256 2 58387 492964499 0 08388 2143013105 3 28389 \end{cfa}8390 \end{tabular}8391 \begin{cfa}8392 // same output as above from thread t8393 \end{cfa}8394 \end{cquote}8395 \caption{Concurrent PRNG}8396 \label{f:ConcurrentPRNG}8397 \end{figure}8398 \end{itemize}8399 8400 8401 8108 \section{Multi-precision Integers} 8402 8109 \label{s:MultiPrecisionIntegers} … … 8603 8310 \end{tabular} 8604 8311 \end{cquote} 8605 8312 \small 8606 8313 \begin{cfa} 8607 8314 Factorial Numbers -
libcfa/src/Makefile.am
r9ef9644 ra556492 72 72 common.hfa \ 73 73 fstream.hfa \ 74 heap.hfa \ 74 75 iostream.hfa \ 75 76 iterator.hfa \ … … 101 102 startup.hfa \ 102 103 virtual.c \ 103 virtual.h \ 104 heap.cc \ 105 heap.h 104 virtual.h 106 105 107 106 # not all platforms support concurrency, add option do disable it … … 173 172 174 173 -include $(libdeps) 175 -include $(DEPDIR)/heap.Plo176 174 177 175 thread_libdeps = $(join \ -
libcfa/src/concurrency/coroutine.cfa
r9ef9644 ra556492 85 85 // minimum feasible stack size in bytes 86 86 static const size_t MinStackSize = 1000; 87 88 extern "C" { 89 extern size_t __cfa_page_size; // architecture pagesize HACK, should go in proper runtime singleton 90 extern int __map_prot; 91 } 87 extern size_t __page_size; // architecture pagesize HACK, should go in proper runtime singleton 88 extern int __map_prot; 92 89 93 90 void __stack_prepare( __stack_info_t * this, size_t create_size ); … … 160 157 [void *, size_t] __stack_alloc( size_t storageSize ) { 161 158 const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment 162 assert(__ cfa_page_size != 0l);159 assert(__page_size != 0l); 163 160 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 164 size = ceiling(size, __ cfa_page_size);161 size = ceiling(size, __page_size); 165 162 166 163 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. 167 164 void * storage; 168 165 #if CFA_COROUTINE_USE_MMAP 169 storage = mmap(0p, size + __ cfa_page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);166 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 170 167 if(storage == ((void*)-1)) { 171 168 abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) ); 172 169 } 173 if ( mprotect( storage, __ cfa_page_size, PROT_NONE ) == -1 ) {170 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) { 174 171 abort( "coroutine stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) ); 175 172 } // if 176 storage = (void *)(((intptr_t)storage) + __ cfa_page_size);173 storage = (void *)(((intptr_t)storage) + __page_size); 177 174 #else 178 175 __cfaabi_dbg_debug_do( 179 storage = memalign( __ cfa_page_size, size + __cfa_page_size );176 storage = memalign( __page_size, size + __page_size ); 180 177 ); 181 178 __cfaabi_dbg_no_debug_do( … … 184 181 185 182 __cfaabi_dbg_debug_do( 186 if ( mprotect( storage, __ cfa_page_size, PROT_NONE ) == -1 ) {183 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) { 187 184 abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) ); 188 185 } 189 storage = (void *)(((intptr_t)storage) + __ cfa_page_size);186 storage = (void *)(((intptr_t)storage) + __page_size); 190 187 ); 191 188 #endif … … 201 198 #if CFA_COROUTINE_USE_MMAP 202 199 size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t); 203 storage = (void *)(((intptr_t)storage) - __ cfa_page_size);204 if(munmap(storage, size + __ cfa_page_size) == -1) {200 storage = (void *)(((intptr_t)storage) - __page_size); 201 if(munmap(storage, size + __page_size) == -1) { 205 202 abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) ); 206 203 } 207 204 #else 208 205 __cfaabi_dbg_debug_do( 209 storage = (char*)(storage) - __ cfa_page_size;210 if ( mprotect( storage, __ cfa_page_size, __map_prot ) == -1 ) {206 storage = (char*)(storage) - __page_size; 207 if ( mprotect( storage, __page_size, __map_prot ) == -1 ) { 211 208 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) ); 212 209 } -
libcfa/src/concurrency/kernel.hfa
r9ef9644 ra556492 173 173 174 174 static inline void ?{}(__timestamp_t & this) { this.tv = 0; this.ma = 0; } 175 static inline void ^?{}(__timestamp_t & ) {}175 static inline void ^?{}(__timestamp_t & this) {} 176 176 177 177 struct __attribute__((aligned(128))) __ready_queue_caches_t; -
libcfa/src/concurrency/kernel/startup.cfa
r9ef9644 ra556492 18 18 19 19 // C Includes 20 #include <errno.h> // errno20 #include <errno.h> // errno 21 21 #include <signal.h> 22 #include <string.h> // strerror23 #include <unistd.h> // sysconf22 #include <string.h> // strerror 23 #include <unistd.h> // sysconf 24 24 25 25 extern "C" { 26 #include <limits.h>// PTHREAD_STACK_MIN27 #include <unistd.h> // syscall28 #include <sys/eventfd.h> // eventfd29 #include <sys/mman.h>// mprotect30 #include <sys/resource.h>// getrlimit26 #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 31 31 } 32 32 33 33 // CFA Includes 34 34 #include "kernel_private.hfa" 35 #include "startup.hfa" // STARTUP_PRIORITY_XXX35 #include "startup.hfa" // STARTUP_PRIORITY_XXX 36 36 #include "limits.hfa" 37 37 #include "math.hfa" … … 102 102 extern void __wake_proc(processor *); 103 103 extern int cfa_main_returned; // from interpose.cfa 104 uint32_t __global_random_prime = 4_294_967_291u, __global_random_mask = false;104 extern uint32_t __global_random_seed; 105 105 106 106 //----------------------------------------------------------------------------- … … 122 122 extern "C" { 123 123 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters; 124 extern size_t __cfa_page_size; 125 extern int __map_prot; 126 } 124 } 125 126 extern size_t __page_size; 127 extern int __map_prot; 127 128 128 129 //----------------------------------------------------------------------------- … … 489 490 preferred = ready_queue_new_preferred(); 490 491 last_proc = 0p; 491 random_state = __global_random_ mask ? __global_random_prime : __global_random_prime ^ rdtscl();492 random_state = __global_random_seed; 492 493 #if defined( __CFA_WITH_VERIFY__ ) 493 494 canary = 0x0D15EA5E0D15EA5Ep; … … 573 574 } 574 575 576 extern size_t __page_size; 575 577 void ^?{}(processor & this) with( this ){ 576 578 /* paranoid */ verify( !__atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ); … … 738 740 void * stack; 739 741 #if CFA_PROCESSOR_USE_MMAP 740 stacksize = ceiling( stacksize, __ cfa_page_size ) + __cfa_page_size;742 stacksize = ceiling( stacksize, __page_size ) + __page_size; 741 743 stack = mmap(0p, stacksize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 742 744 if(stack == ((void*)-1)) { 743 745 abort( "pthread stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) ); 744 746 } 745 if ( mprotect( stack, __ cfa_page_size, PROT_NONE ) == -1 ) {747 if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) { 746 748 abort( "pthread stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) ); 747 749 } // if 748 750 #else 749 751 __cfaabi_dbg_debug_do( 750 stack = memalign( __ cfa_page_size, stacksize + __cfa_page_size );752 stack = memalign( __page_size, stacksize + __page_size ); 751 753 // pthread has no mechanism to create the guard page in user supplied stack. 752 if ( mprotect( stack, __ cfa_page_size, PROT_NONE ) == -1 ) {754 if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) { 753 755 abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) ); 754 756 } // if … … 777 779 check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" ); 778 780 assert( stacksize >= PTHREAD_STACK_MIN ); 779 stacksize += __ cfa_page_size;781 stacksize += __page_size; 780 782 781 783 if(munmap(stack, stacksize) == -1) { … … 785 787 __cfaabi_dbg_debug_do( 786 788 // pthread has no mechanism to create the guard page in user supplied stack. 787 if ( mprotect( stack, __ cfa_page_size, __map_prot ) == -1 ) {789 if ( mprotect( stack, __page_size, __map_prot ) == -1 ) { 788 790 abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) ); 789 791 } // if -
libcfa/src/concurrency/thread.cfa
r9ef9644 ra556492 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 12 15:24:18 202213 // Update Count : 6612 // Last Modified On : Sat Jan 15 14:34:58 2022 13 // Update Count : 45 14 14 // 15 15 … … 25 25 #include "invoke.h" 26 26 27 extern uint32_t __global_random_seed , __global_random_prime, __global_random_mask;27 extern uint32_t __global_random_seed; 28 28 29 29 //----------------------------------------------------------------------------- … … 45 45 preferred = ready_queue_new_preferred(); 46 46 last_proc = 0p; 47 random_state = __global_random_ mask ? __global_random_prime : __global_random_prime ^ rdtscl();47 random_state = __global_random_seed; 48 48 #if defined( __CFA_WITH_VERIFY__ ) 49 49 canary = 0x0D15EA5E0D15EA5Ep; … … 176 176 177 177 void set_seed( uint32_t seed ) { 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; 178 active_thread()->random_state = __global_random_seed = seed; 179 GENERATOR( active_thread()->random_state ); 183 180 } // set_seed 184 181 -
libcfa/src/concurrency/thread.hfa
r9ef9644 ra556492 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 11 16:34:07202213 // Update Count : 2012 // Last Modified On : Wed Feb 9 22:10:14 2022 13 // Update Count : 14 14 14 // 15 15 … … 131 131 132 132 //---------- 133 // prng134 133 static inline { 135 134 uint32_t prng( thread$ & th ) __attribute__(( warn_unused_result )) { return LCG( th.random_state ); } // [0,UINT_MAX] 136 135 uint32_t prng( thread$ & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u) 137 136 uint32_t prng( thread$ & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u] 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 137 } // prng 144 138 145 139 // Local Variables: // -
libcfa/src/startup.cfa
r9ef9644 ra556492 27 27 void __cfaabi_appready_startup( void ) { 28 28 tzset(); // initialize time global variables 29 #ifdef __CFA_DEBUG__ FIXME29 #ifdef __CFA_DEBUG__ 30 30 extern void heapAppStart(); 31 31 heapAppStart(); 32 #endif // __CFA_DEBUG__ FIXME32 #endif // __CFA_DEBUG__ 33 33 } // __cfaabi_appready_startup 34 34 35 35 void __cfaabi_appready_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_APPREADY ) )); 36 36 void __cfaabi_appready_shutdown( void ) { 37 #ifdef __CFA_DEBUG__ FIXME37 #ifdef __CFA_DEBUG__ 38 38 extern void heapAppStop(); 39 39 heapAppStop(); 40 #endif // __CFA_DEBUG__ FIXME40 #endif // __CFA_DEBUG__ 41 41 } // __cfaabi_appready_shutdown 42 42 -
libcfa/src/stdhdr/malloc.h
r9ef9644 ra556492 18 18 } // extern "C" 19 19 20 #include <heap.h >20 #include <heap.hfa> 21 21 22 22 // Local Variables: // -
libcfa/src/stdlib.hfa
r9ef9644 ra556492 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 12 17:22:25202213 // Update Count : 64 312 // Last Modified On : Thu Feb 10 18:34:58 2022 13 // Update Count : 641 14 14 // 15 15 … … 21 21 22 22 #include <stdlib.h> // *alloc, strto*, ato* 23 #include <heap.h >23 #include <heap.hfa> 24 24 25 25 … … 209 209 210 210 forall( TT... | { T * alloc_internal$( void *, T *, size_t, size_t, S_fill(T), TT ); } ) { 211 T * alloc_internal$( void * , T * , size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) {211 T * alloc_internal$( void * , T * Realloc, size_t Align, size_t Dim, S_fill(T) Fill, T_resize Resize, TT rest) { 212 212 return alloc_internal$( Resize, (T*)0p, Align, Dim, Fill, rest); 213 213 } 214 214 215 T * alloc_internal$( void * , T * , size_t Align, size_t Dim, S_fill(T) Fill, S_realloc(T) Realloc, TT rest) {215 T * alloc_internal$( void * Resize, T * , size_t Align, size_t Dim, S_fill(T) Fill, S_realloc(T) Realloc, TT rest) { 216 216 return alloc_internal$( (void*)0p, Realloc, Align, Dim, Fill, rest); 217 217 } … … 389 389 // Declaration : 390 390 // PRNG sprng = { 1009 } - set starting seed versus random seed 391 // 391 // 392 392 // Interface : 393 393 // set_seed( sprng, 1009 ) - set starting seed for ALL kernel threads versus random seed … … 412 412 void set_seed( PRNG & prng, uint32_t seed_ ); 413 413 static inline { 414 void ?{}( PRNG & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); }// random seed415 void ?{}( PRNG & prng, uint32_t seed ) with( prng ) { callcnt = 0;set_seed( prng, seed ); } // fixed seed414 void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); } // random seed 415 void ?{}( PRNG & prng, uint32_t seed ) { set_seed( prng, seed ); } // fixed seed 416 416 uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed 417 417 uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return LCG( state ); } // [0,UINT_MAX] -
src/AST/Convert.hpp
r9ef9644 ra556492 20 20 class Declaration; 21 21 namespace ast { 22 classTranslationUnit;22 struct TranslationUnit; 23 23 }; 24 24 -
src/AST/Fwd.hpp
r9ef9644 ra556492 140 140 typedef unsigned int UniqueId; 141 141 142 classTranslationUnit;142 struct TranslationUnit; 143 143 // TODO: Get from the TranslationUnit: 144 144 extern ptr<Type> sizeType; -
src/AST/Pass.hpp
r9ef9644 ra556492 239 239 private: 240 240 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. 241 // Regular nodes 246 242 template< typename node_t > 247 using generic_call_accept_result = 248 std::enable_if< 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 * ); 253 254 template< typename node_t > 255 auto call_accept( const node_t * node ) 256 -> typename std::enable_if< 249 257 !std::is_base_of<ast::Expr, node_t>::value && 250 258 !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 259 , result1< 260 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 254 261 > 255 >; 256 257 template< typename node_t > 258 auto call_accept( const node_t * node ) 259 -> typename generic_call_accept_result<node_t>::type; 262 >::type; 260 263 261 264 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 262 __pass::result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 263 265 result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 266 267 // Container of statements 264 268 template< template <class...> class container_t > 265 __pass::resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & ); 266 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 267 316 template< template <class...> class container_t, typename node_t > 268 __pass::resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container ); 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 ); 269 327 270 328 public: -
src/AST/Pass.impl.hpp
r9ef9644 ra556492 111 111 } 112 112 113 113 114 //------------------------------ 114 115 /// Check if value was mutated, different for pointers and containers … … 124 125 } 125 126 127 128 template< typename core_t > 126 129 template< typename node_t > 127 130 template< typename object_t, typename super_t, typename field_t > 128 void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field) {131 void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) { 129 132 object->*field = value; 130 133 } … … 133 136 template< typename node_t > 134 137 auto ast::Pass< core_t >::call_accept( const node_t * node ) 135 -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type 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 136 145 { 137 146 __pedantic_pass_assert( __visit_children() ); … … 142 151 143 152 auto nval = node->accept( *this ); 144 __pass::result1<153 ast::Pass< core_t >::result1< 145 154 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 146 155 > res; … … 151 160 152 161 template< typename core_t > 153 __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {162 typename ast::Pass< core_t >::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 154 163 __pedantic_pass_assert( __visit_children() ); 155 164 __pedantic_pass_assert( expr ); … … 165 174 166 175 template< typename core_t > 167 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {176 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 168 177 __pedantic_pass_assert( __visit_children() ); 169 178 __pedantic_pass_assert( stmt ); … … 174 183 175 184 template< typename core_t > 176 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {185 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 177 186 __pedantic_pass_assert( __visit_children() ); 178 187 __pedantic_pass_assert( stmt ); … … 224 233 } 225 234 235 template< typename core_t > 226 236 template< template <class...> class container_t > 227 237 template< typename object_t, typename super_t, typename field_t > 228 void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {238 void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) { 229 239 auto & container = object->*field; 230 240 __pedantic_pass_assert( container.size() <= values.size() ); … … 233 243 234 244 container_t<ptr<Stmt>> nvals; 235 for (delta & d : values) {236 if ( d.is_old ) {245 for(delta & d : values) { 246 if( d.is_old ) { 237 247 __pedantic_pass_assert( cit.idx <= d.old_idx ); 238 248 std::advance( cit, d.old_idx - cit.idx ); 239 249 nvals.push_back( std::move( (*cit).val) ); 240 250 } else { 241 nvals.push_back( std::move(d.n ew_val) );251 nvals.push_back( std::move(d.nval) ); 242 252 } 243 253 } 244 254 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; 255 object->*field = std::move(nvals); 274 256 } 275 257 276 258 template< typename core_t > 277 259 template< template <class...> class container_t > 278 __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {260 typename ast::Pass< core_t >::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 279 261 __pedantic_pass_assert( __visit_children() ); 280 262 if( statements.empty() ) return {}; … … 303 285 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 304 286 305 __pass::resultNstmt<container_t> new_kids;287 resultNstmt<container_t> new_kids; 306 288 for( auto value : enumerate( statements ) ) { 307 289 try { … … 345 327 } 346 328 329 template< typename core_t > 347 330 template< template <class...> class container_t, typename node_t > 348 331 template< typename object_t, typename super_t, typename field_t > 349 void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {332 void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) { 350 333 auto & container = object->*field; 351 334 __pedantic_pass_assert( container.size() == values.size() ); … … 363 346 template< typename core_t > 364 347 template< template <class...> class container_t, typename node_t > 365 __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {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 ) { 366 349 __pedantic_pass_assert( __visit_children() ); 367 350 if( container.empty() ) return {}; … … 395 378 if ( ! errors.isEmpty() ) { throw errors; } 396 379 397 return ast:: __pass::resultN<container_t, node_t>{ mutated,new_kids };380 return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated, new_kids }; 398 381 } 399 382 -
src/AST/Pass.proto.hpp
r9ef9644 ra556492 23 23 class Pass; 24 24 25 classTranslationUnit;25 struct TranslationUnit; 26 26 27 27 struct PureVisitor; … … 123 123 static constexpr bool value = std::is_void< ret_t >::value || 124 124 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 );171 125 }; 172 126 -
src/AST/TranslationUnit.hpp
r9ef9644 ra556492 23 23 namespace ast { 24 24 25 class TranslationUnit { 26 public: 25 struct TranslationUnit { 27 26 std::list< ptr< Decl > > decls; 28 27 -
src/CodeGen/FixNames.h
r9ef9644 ra556492 20 20 class Declaration; 21 21 namespace ast { 22 classTranslationUnit;22 struct TranslationUnit; 23 23 } 24 24 -
src/Common/CodeLocation.h
r9ef9644 ra556492 25 25 /// Create a new unset CodeLocation. 26 26 CodeLocation() = default; 27 27 28 28 29 /// Create a new CodeLocation with the given values. -
src/Common/CodeLocationTools.hpp
r9ef9644 ra556492 17 17 18 18 namespace ast { 19 classTranslationUnit;19 struct TranslationUnit; 20 20 } 21 21 -
src/Common/ResolvProtoDump.hpp
r9ef9644 ra556492 17 17 18 18 namespace ast { 19 classTranslationUnit;19 struct TranslationUnit; 20 20 } 21 21 -
src/Concurrency/Waitfor.cc
r9ef9644 ra556492 372 372 ), 373 373 new ListInit( 374 map_range < std::list<Initializer*> > ( clause.target.arguments, [](Expression * expr ){ 375 return new SingleInit( expr ); 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 ); 376 392 }) 377 393 ) -
src/ControlStruct/MultiLevelExit.cpp
r9ef9644 ra556492 176 176 auto mutStmt = mutate( stmt ); 177 177 // A child statement may set the break label. 178 mutStmt->kids = fixBlock( stmt->kids, false);178 mutStmt->kids = move( fixBlock( stmt->kids, false ) ); 179 179 180 180 if ( isLabeled ) { -
src/InitTweak/FixInit.h
r9ef9644 ra556492 21 21 class Declaration; 22 22 namespace ast { 23 classTranslationUnit;23 struct TranslationUnit; 24 24 } 25 25 -
src/MakeLibCfa.h
r9ef9644 ra556492 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // MakeLibCfa.h -- 7 // MakeLibCfa.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 20 20 class Declaration; 21 21 namespace ast { 22 classTranslationUnit;22 struct TranslationUnit; 23 23 } 24 24 -
src/Parser/parser.yy
r9ef9644 ra556492 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 11 14:26:15202213 // Update Count : 51 7412 // Last Modified On : Tue Feb 1 11:06:13 2022 13 // Update Count : 5167 14 14 // 15 15 … … 1197 1197 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); } 1198 1198 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1199 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; } 1199 1200 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); } 1200 1201 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) … … 1203 1204 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); } 1204 1205 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1206 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; } 1205 1207 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); } 1206 1208 | FOR '(' ')' statement // CFA => for ( ;; ) … … 1209 1211 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); } 1210 1212 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1213 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; } 1211 1214 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); } 1212 1215 ; … … 2726 2729 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 2727 2730 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); } 2728 | EXTERN STRINGliteral2729 {2730 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall"2731 linkage = LinkageSpec::update( yylloc, linkage, $2 );2732 }2733 up external_definition down2734 {2735 linkage = linkageStack.top();2736 linkageStack.pop();2737 $$ = $5;2738 }2739 2731 | EXTERN STRINGliteral // C++-style linkage specifier 2740 2732 { -
src/ResolvExpr/Resolver.cc
r9ef9644 ra556492 1112 1112 } 1113 1113 1114 1114 1115 1115 } // anonymous namespace 1116 1116 /// Establish post-resolver invariants for expressions … … 1158 1158 1159 1159 namespace { 1160 1160 1161 1161 1162 1162 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the … … 1905 1905 1906 1906 clause2.target.args.reserve( clause.target.args.size() ); 1907 const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );1908 1907 for ( auto arg : argsCandidates.front() ) { 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 ) ); 1908 clause2.target.args.emplace_back( std::move( arg->expr ) ); 1924 1909 } 1925 1910 … … 2092 2077 if (auto functionDecl = decl.as<ast::FunctionDecl>()) { 2093 2078 // xxx - can intrinsic gen ever fail? 2094 if (functionDecl->linkage == ast::Linkage::AutoGen) { 2079 if (functionDecl->linkage == ast::Linkage::AutoGen) { 2095 2080 auto mutDecl = mutate(functionDecl); 2096 2081 mutDecl->isDeleted = true; -
src/ResolvExpr/Resolver.h
r9ef9644 ra556492 35 35 class StmtExpr; 36 36 class SymbolTable; 37 classTranslationUnit;37 struct TranslationUnit; 38 38 class Type; 39 39 class TypeEnvironment; … … 72 72 ast::ptr< ast::Init > resolveCtorInit( 73 73 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab ); 74 /// Resolves a statement expression 74 /// Resolves a statement expression 75 75 const ast::Expr * resolveStmtExpr( 76 76 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab ); -
tests/PRNG.cfa
r9ef9644 ra556492 8 8 // Created On : Wed Dec 29 09:38:12 2021 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Sat Feb 12 12:23:57202211 // Update Count : 3 4210 // Last Modified On : Fri Feb 11 08:16:43 2022 11 // Update Count : 328 12 12 // 13 13 … … 20 20 #include <malloc.h> // malloc_stats 21 21 #include <locale.h> // setlocale 22 #include <mutex_stmt.hfa>23 22 24 23 // FIX ME: spurious characters appear in output … … 51 50 } // for 52 51 double std = sqrt( sum / BUCKETS ); 53 mutex( sout )sout | "trials" | TRIALS | "buckets" | BUCKETS54 | "min" | min | "max" | max55 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%";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)) | "%"; 56 55 } // avgstd 57 56 58 59 57 uint32_t seed = 1009; 58 60 59 61 60 thread T1 {}; … … 95 94 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 96 95 for ( TRIALS ) { 97 buckets[prng( th ) % BUCKETS] += 1; // concurrent96 buckets[prng( (thread$ &)th ) % BUCKETS] += 1; // concurrent 98 97 } // for 99 98 avgstd( buckets ); -
tests/meta/dumpable.cfa
r9ef9644 ra556492 72 72 } 73 73 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; 74 if((buf.f_bsize * buf.f_bavail) < 536870912) { 75 serr | "Available diskspace is less than ~500Mb: " | (buf.f_bsize * buf.f_bavail); 78 76 } 79 77
Note:
See TracChangeset
for help on using the changeset viewer.