Changes in / [7c782af:c71b256]


Ignore:
Files:
1 deleted
49 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    r7c782af rc71b256  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Feb 13 08:19:07 2018
    14 %% Update Count     : 367
     13%% Last Modified On : Sun Feb  4 10:38:26 2018
     14%% Update Count     : 365
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    177177\makeatother
    178178
    179 \newenvironment{cquote}{%
    180         \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
     179\newenvironment{quote2}{%
     180        \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}%
    181181        \item\relax
    182182}{%
    183183        \endlist
    184 }% cquote
     184}% quote2
    185185
    186186\newenvironment{rationale}{%
    187   \begin{cquote}\noindent$\Box$\enspace
     187  \begin{quote2}\noindent$\Box$\enspace
    188188}{%
    189   \hfill\enspace$\Box$\end{cquote}
     189  \hfill\enspace$\Box$\end{quote2}
    190190}%
    191191
     
    201201\newenvironment{syntax}{
    202202\paragraph{Syntax}
    203 \begin{cquote}
     203\begin{quote2}
    204204\begin{description}[noitemsep,leftmargin=\parindentlnth]
    205205}{
    206206\end{description}
    207 \end{cquote}
     207\end{quote2}
    208208}
    209209% \def\syntax{\paragraph{Syntax}\trivlist\parindent=.5in\item[\hskip.5in]}
  • doc/papers/general/Paper.tex

    r7c782af rc71b256  
    44\usepackage{epic,eepic}
    55\usepackage{xspace,calc,comment}
    6 \usepackage{upquote}                                            % switch curled `'" to straight
    7 \usepackage{listings}                                           % format program code
    8 \usepackage{enumitem}
    9 \usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
     6\usepackage{upquote}                                                                    % switch curled `'" to straight
     7\usepackage{listings}                                                                   % format program code
    108\usepackage{rotating}
    119\usepackage[usenames]{color}
    12 \usepackage{pslatex}                                            % reduce size of san serif font
     10\usepackage{pslatex}                                    % reduce size of san serif font
    1311\usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
    1412
    1513\setlength{\textheight}{9in}
    1614%\oddsidemargin 0.0in
    17 \renewcommand{\topfraction}{0.8}                        % float must be greater than X of the page before it is forced onto its own page
    18 \renewcommand{\bottomfraction}{0.8}                     % float must be greater than X of the page before it is forced onto its own page
    19 \renewcommand{\floatpagefraction}{0.8}          % float must be greater than X of the page before it is forced onto its own page
    20 \renewcommand{\textfraction}{0.0}                       % the entire page maybe devoted to floats with no text on the page at all
    21 
    22 \lefthyphenmin=4                                                        % hyphen only after 4 characters
     15\renewcommand{\topfraction}{0.8}                % float must be greater than X of the page before it is forced onto its own page
     16\renewcommand{\bottomfraction}{0.8}             % float must be greater than X of the page before it is forced onto its own page
     17\renewcommand{\floatpagefraction}{0.8}  % float must be greater than X of the page before it is forced onto its own page
     18\renewcommand{\textfraction}{0.0}               % the entire page maybe devoted to floats with no text on the page at all
     19
     20\lefthyphenmin=4                                                % hyphen only after 4 characters
    2321\righthyphenmin=4
    2422
     
    2624
    2725\newcommand{\CFAIcon}{\textsf{C}\raisebox{\depth}{\rotatebox{180}{\textsf{A}}}\xspace} % Cforall symbolic name
    28 \newcommand{\CFA}{\protect\CFAIcon}             % safe for section/caption
    29 \newcommand{\CFL}{\textrm{Cforall}\xspace}      % Cforall symbolic name
    30 \newcommand{\Celeven}{\textrm{C11}\xspace}      % C11 symbolic name
     26\newcommand{\CFA}{\protect\CFAIcon} % safe for section/caption
     27\newcommand{\CFL}{\textrm{Cforall}\xspace} % Cforall symbolic name
     28\newcommand{\Celeven}{\textrm{C11}\xspace} % C11 symbolic name
    3129\newcommand{\CC}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}\xspace} % C++ symbolic name
    3230\newcommand{\CCeleven}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
     
    5856\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    5957
    60 \newlength{\gcolumnposn}                                        % temporary hack because lstlisting does not handle tabs correctly
     58\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    6159\newlength{\columnposn}
    6260\setlength{\gcolumnposn}{2.75in}
     
    7472
    7573% Latin abbreviation
    76 \newcommand{\abbrevFont}{\textit}                       % set empty for no italics
     74\newcommand{\abbrevFont}{\textit}       % set empty for no italics
    7775\newcommand{\EG}{\abbrevFont{e}.\abbrevFont{g}.}
    7876\newcommand*{\eg}{%
     
    105103
    106104\newenvironment{cquote}{%
    107         \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
     105        \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}%
    108106        \item\relax
    109107}{%
     
    189187
    190188
    191 \section{Introduction}
     189\section{Introduction and Background}
    192190
    193191The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects.
     
    195193The TIOBE~\cite{TIOBE} ranks the top 5 most popular programming languages as: Java 16\%, \Textbf{C 7\%}, \Textbf{\CC 5\%}, \Csharp 4\%, Python 4\% = 36\%, where the next 50 languages are less than 3\% each with a long tail.
    196194The top 3 rankings over the past 30 years are:
     195\lstDeleteShortInline@%
    197196\begin{center}
    198197\setlength{\tabcolsep}{10pt}
    199 \lstDeleteShortInline@%
    200198\begin{tabular}{@{}rccccccc@{}}
    201199                & 2017  & 2012  & 2007  & 2002  & 1997  & 1992  & 1987          \\ \hline
     
    204202\CC             & 3             & 3             & 3             & 3             & 2             & 2             & 4                     \\
    205203\end{tabular}
     204\end{center}
    206205\lstMakeShortInline@%
    207 \end{center}
    208206Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    209207In many cases, \CC is often used solely as a better C.
     
    226224The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance.
    227225
    228 \section{Polymorphic Functions}
    229 
    230 \CFA introduces both ad-hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
    231 
    232 \subsection{Name Overloading}
    233 
    234 C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax.
    235 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C.
    236 Code generation for these overloaded functions and variables is implemented by the usual approach of mangling the identifier names to include a representation of their type, while \CFA decides which overload to apply based on the same ``usual arithmetic conversions'' used in C to disambiguate operator overloads.
    237 As an example:
    238 
    239 \begin{cfa}
    240 int max(int a, int b) { return a < b ? b : a; }  // (1)
    241 double max(double a, double b) { return a < b ? b : a; }  // (2)
    242 
    243 int max = INT_MAX;     // (3)
    244 double max = DBL_MAX;  // (4)
    245 
    246 max(7, -max);   $\C{// uses (1) and (3), by matching int from constant 7}$
    247 max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$
    248 
    249 //max(max, -max);  $\C{// ERROR: ambiguous}$
    250 int m = max(max, -max); $\C{// uses (1) once and (3) twice, by matching return type}$
    251 \end{cfa}
    252 
    253 \Celeven did add @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    254 The macro wrapping the generic expression imposes some limitations; as an example, it could not implement the example above, because the variables @max@ would collide with the functions @max@.
    255 Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the functions dispatched to, which must all have distinct names.
    256 
    257 \subsection{\texorpdfstring{\LstKeywordStyle{forall} Functions}{forall Functions}}
     226
     227\subsection{Polymorphic Functions}
    258228\label{sec:poly-fns}
    259229
     230\CFA{}\hspace{1pt}'s polymorphism was originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
    260231The signature feature of \CFA is parametric-polymorphic functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a @forall@ clause (giving the language its name):
    261232\begin{lstlisting}
     
    286257Crucial to the design of a new programming language are the libraries to access thousands of external software features.
    287258Like \CC, \CFA inherits a massive compatible library-base, where other programming languages must rewrite or provide fragile inter-language communication with C.
    288 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:
     259A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted floating-point array:
    289260\begin{lstlisting}
    290261void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
     
    292263int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 :
    293264                                *(double *)t2 < *(double *)t1 ? 1 : 0; }
    294 double key = 5.0, vals[10] = { /* 10 sorted float values */ };
     265double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ };
    295266double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      $\C{// search sorted array}$
    296267\end{lstlisting}
     
    333304Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    334305
    335 %% Redundant with Section~\ref{sec:libraries} %%
    336 
    337 % Finally, \CFA allows variable overloading:
    338 % \begin{lstlisting}
    339 % short int MAX = ...;   int MAX = ...;  double MAX = ...;
    340 % short int s = MAX;    int i = MAX;    double d = MAX;   $\C{// select correct MAX}$
    341 % \end{lstlisting}
    342 % Here, the single name @MAX@ replaces all the C type-specific names: @SHRT_MAX@, @INT_MAX@, @DBL_MAX@.
     306Finally, \CFA allows variable overloading:
     307\begin{lstlisting}
     308short int MAX = ...;   int MAX = ...;  double MAX = ...;
     309short int s = MAX;    int i = MAX;    double d = MAX;   $\C{// select correct MAX}$
     310\end{lstlisting}
     311Here, the single name @MAX@ replaces all the C type-specific names: @SHRT_MAX@, @INT_MAX@, @DBL_MAX@.
    343312
    344313\subsection{Traits}
     
    536505In many languages, functions can return at most one value;
    537506however, many operations have multiple outcomes, some exceptional.
    538 Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively.
     507Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and floating-point values, respectively.
    539508\begin{lstlisting}
    540509typedef struct { int quo, rem; } div_t;         $\C{// from include stdlib.h}$
     
    967936
    968937\section{Control Structures}
    969 
    970 \CFA identifies missing and problematic control structures in C, and extends and modifies these control structures to increase functionality and safety.
    971938
    972939
     
    10771044The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
    10781045
    1079 
    10801046\subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}}
    10811047
    1082 There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses.
    1083 
    1084 C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}.
    1085 \CFA provides a shorthand for a non-contiguous list:
    1086 \begin{cquote}
    1087 \lstDeleteShortInline@%
    1088 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1089 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1090 \begin{cfa}
    1091 case 2, 10, 34, 42:
    1092 \end{cfa}
    1093 &
    1094 \begin{cfa}
    1095 case 2: case 10: case 34: case 42:
    1096 \end{cfa}
    1097 \end{tabular}
    1098 \lstMakeShortInline@%
    1099 \end{cquote}
    1100 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.}
    1101 \begin{cquote}
    1102 \lstDeleteShortInline@%
    1103 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1104 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1105 \begin{cfa}
    1106 case 2~42:
    1107 \end{cfa}
    1108 &
    1109 \begin{cfa}
    1110 case 2: case 3: ... case 41: case 42:
    1111 \end{cfa}
    1112 \end{tabular}
    1113 \lstMakeShortInline@%
    1114 \end{cquote}
    1115 and a combination:
    1116 \begin{cfa}
    1117 case -12~-4, -1~5, 14~21, 34~42:
    1118 \end{cfa}
    1119 
    1120 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83});
    1121 \begin{cfa}
    1122 switch ( i ) {
    1123   case 0:
    1124         for ( int i = 0; i < 10; i += 1 ) {
    1125                 ...
    1126   `case 1:`             // no initialization of loop index
    1127                 ...
    1128         }
    1129 }
    1130 \end{cfa}
    1131 \CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality.
    1132 
    1133 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
    1134 \begin{cfa}
    1135 switch ( x ) {
    1136         `int y = 1;`                            $\C{// unreachable initialization}$
    1137         `x = 7;`                                        $\C{// unreachable code without label/branch}$
    1138   case 0:
    1139         ...
    1140         `int z = 0;`                            $\C{// unreachable initialization, cannot appear after case}$
    1141         z = 2;
    1142   case 1:
    1143         `x = z;`                                        $\C{// without fall through, z is undefined}$
    1144 }
    1145 \end{cfa}
    1146 \CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses, but no statements.
    1147 \CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred.
    1148 
    1149 C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through};
    1150 @case@ clauses are made disjoint by the @break@ statement.
    1151 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements.
    1152 \CFA provides a new control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through:
    1153 \begin{cquote}
    1154 \lstDeleteShortInline@%
    1155 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1156 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1157 \begin{cfa}
    1158 `choose` ( day ) {
    1159   case Mon~Thu:
    1160         // program
    1161 
    1162   case Fri:
    1163         // program
    1164         wallet += pay;
    1165         `fallthrough;`
    1166   case Sat:
    1167         // party
    1168         wallet -= party;
    1169 
    1170   case Sun:
    1171         // rest
    1172 
    1173   default:
    1174         // error
    1175 }
    1176 \end{cfa}
    1177 &
    1178 \begin{cfa}
    1179 switch ( day ) {
    1180   case Mon: case Tue: case Wed: case Thu:
    1181         // program
    1182         `break;`
    1183   case Fri:
    1184         // program
    1185         wallet += pay;
    1186 
    1187   case Sat:
    1188         // party
    1189         wallet -= party;
    1190         `break;`
    1191   case Sun:
    1192         // rest
    1193         `break;`
    1194   default:
    1195         // error
    1196 }
    1197 \end{cfa}
    1198 \end{tabular}
    1199 \lstMakeShortInline@%
    1200 \end{cquote}
    1201 Collectively, these enhancements reduce programmer burden and increase readability and safety.
    1202 
    1203 \begin{comment}
     1048\CFA also fixes a number of ergonomic defecits in the @switch@ statements of standard C.
     1049C can specify a number of equivalent cases by using the default ``fall-through'' semantics of @case@ clauses, \eg @case 1: case 2: case 3:@ -- this syntax is cluttered, however, so \CFA includes a more concise list syntax, @case 1, 2, 3:@.
     1050For contiguous ranges, \CFA provides an even more concise range syntax as well, @case 1~3:@; lists of ranges are also allowed in case selectors.
     1051
    12041052Forgotten @break@ statements at the end of @switch@ cases are a persistent sort of programmer error in C, and the @break@ statements themselves introduce visual clutter and an un-C-like keyword-based block delimiter.
    12051053\CFA addresses this error by introducing a @choose@ statement, which works identically to a @switch@ except that its default end-of-case behaviour is to break rather than to fall through for all non-empty cases.
     
    12221070}
    12231071\end{cfa}
    1224 \end{comment}
    1225 
    12261072
    12271073\subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}}
     
    13601206\end{cfa}
    13611207
    1362 % \subsection{Exception Handling ???}
     1208
     1209\subsection{Exception Handling ???}
     1210
    13631211
    13641212\section{Declarations}
     
    14071255\lstDeleteShortInline@%
    14081256\lstset{moredelim=**[is][\color{blue}]{+}{+}}
    1409 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1410 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1257\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1258\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    14111259\begin{cfa}
    14121260+[5] *+ `int` x1;
    14131261+* [5]+ `int` x2;
    1414 `[* [5] int]` f+( int p )+;
     1262+[* [5] int]+ f`( int p )`;
    14151263\end{cfa}
    14161264&
     
    14181266`int` +*+ x1 +[5]+;
    14191267`int` +(*+x2+)[5]+;
    1420 `int (*`f+( int p )+`)[5]`;
     1268+int (*+f`( int p )`+)[5]+;
    14211269\end{cfa}
    14221270\end{tabular}
     
    14291277\begin{cquote}
    14301278\lstDeleteShortInline@%
    1431 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1432 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1279\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1280\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    14331281\begin{cfa}
    14341282`*` int x, y;
     
    14441292\begin{cquote}
    14451293\lstDeleteShortInline@%
    1446 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1447 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1294\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1295\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    14481296\begin{cfa}
    14491297`*` int x;
     
    14621310\begin{cquote}
    14631311\lstDeleteShortInline@%
    1464 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1465 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}}      \\
     1312\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     1313\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    14661314\begin{cfa}
    14671315[ 5 ] int z;
     
    15031351\begin{cquote}
    15041352\lstDeleteShortInline@%
    1505 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1506 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}}      \\
     1353\begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
     1354\multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
    15071355\begin{cfa}
    15081356const * const int x;
     
    15261374\begin{cquote}
    15271375\lstDeleteShortInline@%
    1528 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1529 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}}      \\
     1376\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     1377\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    15301378\begin{cfa}
    15311379extern [ 5 ] int x;
     
    15491397\begin{cquote}
    15501398\lstDeleteShortInline@%
    1551 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1552 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1399\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1400\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    15531401\begin{cfa}
    15541402y = (* int)x;
     
    15671415Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    15681416Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
    1569 
    1570 The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;
    1571 as well, parameter names are optional, \eg:
    1572 \begin{cfa}
    1573 [ int x ] f ();                                                 $\C{// returning int with no parameters}$
    1574 [ * int ] g (int y);                                    $\C{// returning pointer to int with int parameter}$
    1575 [ ] h ( int, char );                                    $\C{// returning no result with int and char parameters}$
    1576 [ * int, int ] j ( int );                               $\C{// returning pointer to int and int, with int parameter}$
    1577 \end{cfa}
    1578 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1579 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list, \eg:
    1580 \begin{cquote}
    1581 \lstDeleteShortInline@%
    1582 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1583 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1584 \begin{cfa}
    1585 [double] foo(), foo( int ), foo( double ) {...}
    1586 \end{cfa}
    1587 &
    1588 \begin{cfa}
    1589 double foo1(), foo2( int ), foo3( double );
    1590 \end{cfa}
    1591 \end{tabular}
    1592 \lstMakeShortInline@%
    1593 \end{cquote}
    1594 \CFA allows the last routine in the list to define its body.
    1595 
    1596 Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
    1597 \begin{cfa}
    1598 extern [ int ] f ( int );
    1599 static [ int ] g ( int );
    1600 \end{cfa}
    1601 
    1602 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    1603 \begin{cfa}
    1604 * [ int x ] () fp;                                              $\C{// pointer to routine returning int with no parameters}$
    1605 * [ * int ] (int y) gp;                                 $\C{// pointer to routine returning pointer to int with int parameter}$
    1606 * [ ] (int,char) hp;                                    $\C{// pointer to routine returning no result with int and char parameters}$
    1607 * [ * int,int ] ( int ) jp;                             $\C{// pointer to routine returning pointer to int and int, with int parameter}$
    1608 \end{cfa}
    1609 While parameter names are optional, \emph{a routine name cannot be specified};
    1610 for example, the following is incorrect:
    1611 \begin{cfa}
    1612 * [ int x ] f () fp;                                    $\C{// routine name "f" is not allowed}$
    1613 \end{cfa}
    16141417
    16151418
     
    17901593In addition to the expressive power, \lstinline|@=| provides a simple path for migrating legacy C code to \CFA, by providing a mechanism to incrementally convert initializers; the \CFA design team decided to introduce a new syntax for this escape hatch because we believe that our RAII implementation will handle the vast majority of code in a desirable way, and we wished to maintain familiar syntax for this common case.
    17911594
    1792 
    1793 \subsection{Type Nesting}
    1794 
    1795 \CFA allows \newterm{type nesting}, and type qualification of the nested types (see Figure~\ref{f:TypeNestingQualification}), where as C hoists (refactors) nested types into the enclosing scope and has no type qualification.
    1796 \begin{figure}
    1797 \centering
    1798 \lstDeleteShortInline@%
    1799 \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
    1800 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}}      & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}}      & \multicolumn{1}{|c}{\textbf{\CFA}}    \\
    1801 \hline
    1802 \begin{cfa}
    1803 struct S {
    1804         enum C { R, G, B };
    1805         struct T {
    1806                 union U { int i, j; };
    1807                 enum C c;
    1808                 short int i, j;
    1809         };
    1810         struct T t;
    1811 } s;
    1812 
    1813 int rtn() {
    1814         s.t.c = R;
    1815         struct T t = { R, 1, 2 };
    1816         enum C c;
    1817         union U u;
    1818 }
    1819 \end{cfa}
    1820 &
    1821 \begin{cfa}
    1822 enum C { R, G, B };
    1823 union U { int i, j; };
    1824 struct T {
    1825         enum C c;
    1826         short int i, j;
    1827 };
    1828 struct S {
    1829         struct T t;
    1830 } s;
    1831        
    1832 
    1833 
    1834 
    1835 
    1836 
    1837 
    1838 \end{cfa}
    1839 &
    1840 \begin{cfa}
    1841 struct S {
    1842         enum C { R, G, B };
    1843         struct T {
    1844                 union U { int i, j; };
    1845                 enum C c;
    1846                 short int i, j;
    1847         };
    1848         struct T t;
    1849 } s;
    1850 
    1851 int rtn() {
    1852         s.t.c = `S.`R;  // type qualification
    1853         struct `S.`T t = { `S.`R, 1, 2 };
    1854         enum `S.`C c;
    1855         union `S.T.`U u;
    1856 }
    1857 \end{cfa}
    1858 \end{tabular}
    1859 \lstMakeShortInline@%
    1860 \caption{Type Nesting / Qualification}
    1861 \label{f:TypeNestingQualification}
    1862 \end{figure}
    1863 In the left example in C, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
    1864 In the right example in \CFA, the types are not hoisted and accessed using the field-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@''.
    1865 
    1866 
    18671595\subsection{Default Parameters}
    18681596
     
    18701598\section{Literals}
    18711599
    1872 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix.
     1600C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and floating-point types are very similar, differing from each other only in suffix.
    18731601In keeping with the general \CFA approach of adding features while respecting ``the C way'' of doing things, we have extended both C's polymorphic zero and typed literal syntax to interoperate with user-defined types, while maintaining a backwards-compatible semantics.
    18741602
     
    18941622struct Weight { double stones; };
    18951623
    1896 void ?{}( Weight & w ) { w.stones = 0; }        $\C{// operations}$
     1624void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$
    18971625void ?{}( Weight & w, double w ) { w.stones = w; }
    18981626Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; }
     
    19031631
    19041632int main() {
    1905         Weight w, hw = { 14 };                                  $\C{// 14 stone}$
     1633        Weight w, hw = { 14 };                  $\C{// 14 stone}$
    19061634        w = 11@`st@ + 1@`lb@;
    19071635        w = 70.3@`kg@;
    19081636        w = 155@`lb@;
    1909         w = 0x_9b_u@`lb@;                                               $\C{// hexadecimal unsigned weight (155)}$
    1910         w = 0_233@`lb@;                                                 $\C{// octal weight (155)}$
     1637        w = 0x_9b_u@`lb@;                               $\C{// hexadecimal unsigned weight (155)}$
     1638        w = 0_233@`lb@;                                 $\C{// octal weight (155)}$
    19111639        w = 5@`st@ + 8@`kg@ + 25@`lb@ + hw;
    19121640}
    19131641\end{cfa}
    19141642}%
    1915 
    1916 
    1917 \section{Libraries}
    1918 \label{sec:libraries}
    1919 
    1920 As stated in Section~\ref{sec:poly-fns}, \CFA inherits a large corpus of library code, where other programming languages must rewrite or provide fragile inter-language communication with C.
    1921 \CFA has replacement libraries condensing hundreds of existing C names into tens of \CFA overloaded names, all without rewriting the actual computations.
    1922 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime.
    1923 The following sections give a glimpse of the interface reduction to many C libraries.
    1924 In many cases, @signed@/@unsigned@ @char@ and @short@ routines are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results.
    1925 
    1926 
    1927 \subsection{Limits}
    1928 
    1929 C library @limits.h@ provides lower and upper bound constants for the basic types.
    1930 \CFA name overloading is used to condense these typed constants, \eg:
    1931 \begin{cquote}
    1932 \lstDeleteShortInline@%
    1933 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1934 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}}       & \multicolumn{1}{c}{\textbf{Usage}}    \\
    1935 \begin{cfa}
    1936 const short int `MIN` = -32768;
    1937 const int `MIN` = -2147483648;
    1938 const long int `MIN` = -9223372036854775808L;
    1939 \end{cfa}
    1940 &
    1941 \begin{cfa}
    1942 short int si = `MIN`;
    1943 int i = `MIN`;
    1944 long int li = `MIN`;
    1945 \end{cfa}
    1946 \end{tabular}
    1947 \lstMakeShortInline@%
    1948 \end{cquote}
    1949 The result is a significant reduction in names to access typed constants, \eg:
    1950 \begin{cquote}
    1951 \lstDeleteShortInline@%
    1952 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1953 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1954 \begin{cfa}
    1955 MIN
    1956 MAX
    1957 M_PI
    1958 M_E
    1959 \end{cfa}
    1960 &
    1961 \begin{cfa}
    1962 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN,
    1963 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX,
    1964 M_PI, M_PIl, M_CPI, M_CPIl,
    1965 M_E, M_El, M_CE, M_CEl
    1966 \end{cfa}
    1967 \end{tabular}
    1968 \lstMakeShortInline@%
    1969 \end{cquote}
    1970 
    1971 
    1972 \subsection{Math}
    1973 
    1974 C library @math.h@ provides many mathematical routines.
    1975 \CFA routine overloading is used to condense these mathematical routines, \eg:
    1976 \begin{cquote}
    1977 \lstDeleteShortInline@%
    1978 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1979 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}}       & \multicolumn{1}{c}{\textbf{Usage}}    \\
    1980 \begin{cfa}
    1981 float `log`( float x );
    1982 double `log`( double );
    1983 double _Complex `log`( double _Complex x );
    1984 \end{cfa}
    1985 &
    1986 \begin{cfa}
    1987 float f = `log`( 3.5 );
    1988 double d = `log`( 3.5 );
    1989 double _Complex dc = `log`( 3.5+0.5I );
    1990 \end{cfa}
    1991 \end{tabular}
    1992 \lstMakeShortInline@%
    1993 \end{cquote}
    1994 The result is a significant reduction in names to access math routines, \eg:
    1995 \begin{cquote}
    1996 \lstDeleteShortInline@%
    1997 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1998 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1999 \begin{cfa}
    2000 log
    2001 sqrt
    2002 sin
    2003 \end{cfa}
    2004 &
    2005 \begin{cfa}
    2006 logf, log, logl, clogf, clog, clogl
    2007 sqrtf, sqrt, sqrtl, csqrtf, csqrt, csqrtl
    2008 sinf, sin, sinl, csinf, csin, csinl
    2009 \end{cfa}
    2010 \end{tabular}
    2011 \lstMakeShortInline@%
    2012 \end{cquote}
    2013 While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a routine name with a single set of floating type(s).
    2014 For example, it is not possible to overload @atan@ for both one and two arguments;
    2015 instead the names @atan@ and @atan2@ are required.
    2016 The key observation is that only a restricted set of type-generic macros are provided for a limited set of routine names, which do not generalize across the type system, as in \CFA.
    2017 
    2018 
    2019 \subsection{Standard}
    2020 
    2021 C library @stdlib.h@ provides many general routines.
    2022 \CFA routine overloading is used to condense these utility routines, \eg:
    2023 \begin{cquote}
    2024 \lstDeleteShortInline@%
    2025 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2026 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}}       & \multicolumn{1}{c}{\textbf{Usage}}    \\
    2027 \begin{cfa}
    2028 unsigned int `abs`( int );
    2029 double `abs`( double );
    2030 double abs( double _Complex );
    2031 \end{cfa}
    2032 &
    2033 \begin{cfa}
    2034 unsigned int i = `abs`( -1 );
    2035 double d = `abs`( -1.5 );
    2036 double d = `abs`( -1.5+0.5I );
    2037 \end{cfa}
    2038 \end{tabular}
    2039 \lstMakeShortInline@%
    2040 \end{cquote}
    2041 The result is a significant reduction in names to access utility routines, \eg:
    2042 \begin{cquote}
    2043 \lstDeleteShortInline@%
    2044 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2045 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    2046 \begin{cfa}
    2047 abs
    2048 strto
    2049 random
    2050 \end{cfa}
    2051 &
    2052 \begin{cfa}
    2053 abs, labs, llabs, fabsf, fabs, fabsl, cabsf, cabs, cabsl
    2054 strtol, strtoul, strtoll, strtoull, strtof, strtod, strtold
    2055 srand48, mrand48, lrand48, drand48
    2056 \end{cfa}
    2057 \end{tabular}
    2058 \lstMakeShortInline@%
    2059 \end{cquote}
    2060 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.
    2061 
    2062 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
    2063 C/\Celeven provide a number of complex and overlapping storage-management operation to support the following capabilities:
    2064 \begin{description}[itemsep=2pt,parsep=0pt]
    2065 \item[fill]
    2066 after allocation the storage is filled with a specified character.
    2067 \item[resize]
    2068 an existing allocation is decreased or increased in size.
    2069 In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied.
    2070 For an increase in storage size, new storage after the copied data may be filled.
    2071 \item[alignment]
    2072 an allocation starts on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
    2073 \item[array]
    2074 the allocation size is scaled to the specified number of array elements.
    2075 An array may be filled, resized, or aligned.
    2076 \end{description}
    2077 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-routines and how all the capabilities can be combined into two \CFA routines.
    2078 
    2079 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size.
    2080 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety:
    2081 \begin{cquote}
    2082 \begin{cfa}[aboveskip=0pt]
    2083 size_t  dim = 10;                                                       $\C{// array dimension}$
    2084 char fill = '\xff';                                                     $\C{// initialization fill value}$
    2085 int * ip;
    2086 \end{cfa}
    2087 \lstDeleteShortInline@%
    2088 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2089 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    2090 \begin{cfa}
    2091 ip = alloc();
    2092 ip = alloc( fill );
    2093 ip = alloc( dim );
    2094 ip = alloc( dim, fill );
    2095 ip = alloc( ip, 2 * dim );
    2096 ip = alloc( ip, 4 * dim, fill );
    2097 
    2098 ip = align_alloc( 16 );
    2099 ip = align_alloc( 16, fill );
    2100 ip = align_alloc( 16, dim );
    2101 ip = align_alloc( 16, dim, fill );
    2102 \end{cfa}
    2103 &
    2104 \begin{cfa}
    2105 ip = (int *)malloc( sizeof( int ) );
    2106 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2107 ip = (int *)malloc( dim * sizeof( int ) );
    2108 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2109 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
    2110 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) );
    2111 
    2112 ip = memalign( 16, sizeof( int ) );
    2113 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2114 ip = memalign( 16, dim * sizeof( int ) );
    2115 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2116 \end{cfa}
    2117 \end{tabular}
    2118 \lstMakeShortInline@%
    2119 \end{cquote}
    2120 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
    2121 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg:
    2122 \begin{cfa}
    2123 struct S { int i, j; };
    2124 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; }
    2125 S * s = new( 2, 3 );                                            $\C{// allocate storage and run constructor}$
    2126 S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    2127 \end{cfa}
    2128 Note, \CC can only initialization array elements via the default constructor.
    2129 
    2130 Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
    2131 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character.
    2132 
    2133 \begin{table}
    2134 \centering
    2135 \lstDeleteShortInline@%
    2136 \lstMakeShortInline~%
    2137 \begin{tabular}{@{}r|r|l|l|l|l@{}}
    2138 \multicolumn{1}{c}{}&           & \multicolumn{1}{c|}{fill}     & resize        & alignment     & array \\
    2139 \hline
    2140 C               & ~malloc~                      & no                    & no            & no            & no    \\
    2141                 & ~calloc~                      & yes (0 only)  & no            & no            & yes   \\
    2142                 & ~realloc~                     & no/copy               & yes           & no            & no    \\
    2143                 & ~memalign~            & no                    & no            & yes           & no    \\
    2144                 & ~posix_memalign~      & no                    & no            & yes           & no    \\
    2145 \hline
    2146 C11             & ~aligned_alloc~       & no                    & no            & yes           & no    \\
    2147 \hline
    2148 \CFA    & ~alloc~                       & yes/copy              & no/yes        & no            & yes   \\
    2149                 & ~align_alloc~         & yes                   & no            & yes           & yes   \\
    2150 \end{tabular}
    2151 \lstDeleteShortInline~%
    2152 \lstMakeShortInline@%
    2153 \caption{Storage-Management Operations}
    2154 \label{t:StorageManagementOperations}
    2155 \end{table}
    2156 
    2157 
    2158 \subsection{I/O}
    2159 \label{s:IOLibrary}
    2160 
    2161 The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user defined types in a consistent way.
    2162 The approach combines ideas from \CC and Python.
    2163 The \CFA header file for the I/O library is @fstream@.
    2164 
    2165 The common case is printing out a sequence of variables separated by whitespace.
    2166 \begin{cquote}
    2167 \lstDeleteShortInline@%
    2168 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2169 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{\CC}}      \\
    2170 \begin{cfa}
    2171 int x = 1, y = 2, z = 3;
    2172 sout | x `|` y `|` z | endl;
    2173 \end{cfa}
    2174 &
    2175 \begin{cfa}
    2176 
    2177 cout << x `<< " "` << y `<< " "` << z << endl;
    2178 \end{cfa}
    2179 \\
    2180 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    2181 1` `2` `3
    2182 \end{cfa}
    2183 &
    2184 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    2185 1 2 3
    2186 \end{cfa}
    2187 \end{tabular}
    2188 \lstMakeShortInline@%
    2189 \end{cquote}
    2190 The \CFA form has half the characters of the \CC form, and is similar to Python I/O with respect to implicit separators.
    2191 Similar simplification occurs for tuple I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
    2192 \begin{cfa}
    2193 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    2194 sout | t1 | t2 | endl;                                  $\C{// print tuples}$
    2195 \end{cfa}
    2196 \begin{cfa}[showspaces=true,aboveskip=0pt]
    2197 1`, `2`, `3 4`, `5`, `6
    2198 \end{cfa}
    2199 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
    2200 Therefore, fewer output expressions require parenthesis.
    2201 \begin{cquote}
    2202 \lstDeleteShortInline@%
    2203 \begin{tabular}{@{}ll@{}}
    2204 \textbf{\CFA:}
    2205 &
    2206 \begin{cfa}
    2207 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
    2208 \end{cfa}
    2209 \\
    2210 \textbf{\CC:}
    2211 &
    2212 \begin{cfa}
    2213 cout << x * 3 << y + 1 << `(`z << 2`)` << `(`x == y`)` << (x | y) << (x || y) << (x > z ? 1 : 2) << endl;
    2214 \end{cfa}
    2215 \\
    2216 \textbf{output:}
    2217 &
    2218 \begin{cfa}[showspaces=true,aboveskip=0pt]
    2219 3 3 12 0 3 1 2
    2220 \end{cfa}
    2221 \end{tabular}
    2222 \lstMakeShortInline@%
    2223 \end{cquote}
    2224 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    2225 
    2226 The implicit separator character (space/blank) is a separator not a terminator.
    2227 The rules for implicitly adding the separator are:
    2228 \begin{itemize}[itemsep=2pt,parsep=0pt]
    2229 \item
    2230 A separator does not appear at the start or end of a line.
    2231 \item
    2232 A separator does not appear before or after a character literal or variable.
    2233 \item
    2234 A separator does not appear before or after a null (empty) C string, which is a local mechanism to disable insertion of the separator character.
    2235 \item
    2236 A separator does not appear before a C string starting with the characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$@
    2237 \item
    2238 A seperator does not appear after a C string ending with the characters: \lstinline[basicstyle=\tt]@,.;!?)]}%@
    2239 \item
    2240 {\lstset{language=CFA,deletedelim=**[is][]{`}{`}}
    2241 A seperator does not appear before or after a C string begining/ending with the quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@
    2242 }%
    2243 \item
    2244 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
    2245 \end{itemize}
    2246 
    2247 
    2248 \subsection{Multi-precision Integers}
    2249 \label{s:MultiPrecisionIntegers}
    2250 
    2251 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP.
    2252 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.
    2253 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@.
    2254 The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces.
    2255 \begin{cquote}
    2256 \lstDeleteShortInline@%
    2257 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}@{\hspace{\parindentlnth}}l@{}}
    2258 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
    2259 \begin{cfa}
    2260 #include <gmp>
    2261 int main( void ) {
    2262         sout | "Factorial Numbers" | endl;
    2263         Int fact = 1;
    2264 
    2265         sout | 0 | fact | endl;
    2266         for ( unsigned int i = 1; i <= 40; i += 1 ) {
    2267                 fact *= i;
    2268                 sout | i | fact | endl;
    2269         }
    2270 }
    2271 \end{cfa}
    2272 &
    2273 \begin{cfa}
    2274 #include <gmp.h>
    2275 int main( void ) {
    2276         `gmp_printf`( "Factorial Numbers\n" );
    2277         `mpz_t` fact;
    2278         `mpz_init_set_ui`( fact, 1 );
    2279         `gmp_printf`( "%d %Zd\n", 0, fact );
    2280         for ( unsigned int i = 1; i <= 40; i += 1 ) {
    2281                 `mpz_mul_ui`( fact, fact, i );
    2282                 `gmp_printf`( "%d %Zd\n", i, fact );
    2283         }
    2284 }
    2285 \end{cfa}
    2286 \end{tabular}
    2287 \lstMakeShortInline@%
    2288 \end{cquote}
    2289 
    22901643
    22911644\section{Evaluation}
     
    23511704
    23521705\begin{table}
    2353 \centering
    23541706\caption{Properties of benchmark code}
    23551707\label{tab:eval}
  • doc/user/user.tex

    r7c782af rc71b256  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Feb 13 08:31:21 2018
    14 %% Update Count     : 3161
     13%% Last Modified On : Wed Jan 31 22:29:25 2018
     14%% Update Count     : 3147
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    161161Like \Index*[C++]{\CC{}}, there may be both an old and new ways to achieve the same effect.
    162162For example, the following programs compare the \CFA, C, and \CC I/O mechanisms, where the programs output the same result.
    163 \begin{cquote}
     163\begin{quote2}
    164164\begin{tabular}{@{}l@{\hspace{1.5em}}l@{\hspace{1.5em}}l@{}}
    165165\multicolumn{1}{c@{\hspace{1.5em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{\CC}}      \\
     
    191191\end{cfa}
    192192\end{tabular}
    193 \end{cquote}
     193\end{quote2}
    194194While the \CFA I/O looks similar to the \Index*[C++]{\CC{}} output style, there are important differences, such as automatic spacing between variables as in \Index*{Python} (see~\VRef{s:IOLibrary}).
    195195
     
    274274
    275275\begin{comment}
    276 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
     276A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating-point array:
    277277\begin{lstlisting}
    278278void * bsearch( const void * key, const void * base, size_t dim, size_t size,
     
    282282                                *(double *)t2 < *(double *)t1 ? 1 : 0; }
    283283
    284 double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
     284double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ };
    285285double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      $\C{// search sorted array}$
    286286\end{lstlisting}
     
    4444440x®_®ff®_®ff;                                                   §\C{// hexadecimal constant}§
    4454450x®_®ef3d®_®aa5c;                                               §\C{// hexadecimal constant}§
    446 3.141®_®592®_®654;                                              §\C{// floating constant}§
    447 10®_®e®_®+1®_®00;                                               §\C{// floating constant}§
    448 0x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating
    449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating long constant}§
     4463.141®_®592®_®654;                                              §\C{// floating point constant}§
     44710®_®e®_®+1®_®00;                                               §\C{// floating point constant}§
     4480x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating point
     4490x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating point long constant}§
    450450L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§;     §\C{// wide character constant}§
    451451\end{cfa}
     
    501501\label{f:HeaderFileInterposition}
    502502\end{figure}
    503 
    504 
    505 \section{Exponentiation Operator}
    506 
    507 C, \CC, and Java (and many other programming languages) have no exponentiation operator\index{exponentiation!operator}\index{operator!exponentiation}, \ie $x^y$, and instead use a routine, like \Indexc{pow}, to perform the exponentiation operation.
    508 \CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@\lstinline$?\?$} and ©?\=?©\index{?\\=?@\lstinline$?\=?$}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$.
    509 The priority of the exponentiation operator is between the cast and multiplicative operators, so that ©w * (int)x \ (int)y * z© is parenthesized as ©((w * (((int)x) \ ((int)y))) * z)©.
    510 
    511 As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
    512 Unsigned integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the base is 2).
    513 Signed integral exponentiation\index{exponentiation!signed integral} is performed with repeated multiplication (or shifting if the base is 2), but yields a floating result because $x^{-y}=1/x^y$.
    514 Hence, it is important to designate exponent integral-constants as unsigned or signed: ©3 \ 3u© return an integral result, while ©3 \ 3© returns a floating result.
    515 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
    516 \begin{cfa}
    517 sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
    518 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
    519 \end{cfa}
    520 Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
    521 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
    522 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
    523 for returning a floating value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents.
    524503
    525504
     
    649628\end{cfa}
    650629The ability to fall-through to the next clause \emph{is} a useful form of control flow, specifically when a sequence of case actions compound:
    651 \begin{cquote}
     630\begin{quote2}
    652631\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    653632\begin{cfa}
     
    677656\end{cfa}
    678657\end{tabular}
    679 \end{cquote}
     658\end{quote2}
    680659In this example, case 2 is always done if case 3 is done.
    681660This control flow is difficult to simulate with if statements or a ©switch© statement without fall-through as code must be duplicated or placed in a separate routine.
     
    751730        ®int y = 1;®                            §\C{// unreachable initialization}§
    752731        ®x = 7;®                                        §\C{// unreachable code without label/branch}§
    753   case 0: ...
     732  case 3: ...
    754733        ...
    755734        ®int z = 0;®                            §\C{// unreachable initialization, cannot appear after case}§
    756735        z = 2;
    757   case 1:
     736  case 3:
    758737        ®x = z;®                                        §\C{// without fall through, z is uninitialized}§
    759738}
     
    840819Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
    841820Therefore, the ©case© clause is extended with a list of values, as in:
    842 \begin{cquote}
     821\begin{quote2}
    843822\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    844823\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    870849\end{cfa}
    871850\end{tabular}
    872 \end{cquote}
     851\end{quote2}
    873852In addition, two forms of subranges are allowed to specify case values: a new \CFA form and an existing GNU C form.\footnote{
    874853The GNU C form \emph{requires} spaces around the ellipse.}
    875 \begin{cquote}
     854\begin{quote2}
    876855\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    877856\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{GNU C}}     \\
     
    903882\end{cfa}
    904883\end{tabular}
    905 \end{cquote}
     884\end{quote2}
    906885Lists of subranges are also allowed.
    907886\begin{cfa}
     
    923902}
    924903\end{C++}
    925 Since \CFA is non-object-oriented, the equivalent object-oriented program looks like:
     904Since CFA is non-object-oriented, the equivalent object-oriented program looks like:
    926905\begin{cfa}
    927906struct S { int i, j; };
    928 int mem( S & ®this® ) {                 §\C{// explicit "this" parameter}§
     907int mem( S &®this® ) {                  §\C{// explicit "this" parameter}§
    929908        ®this.®i = 1;                           §\C{// "this" is not elided}§
    930909        ®this.®j = 2;
    931910}
    932911\end{cfa}
    933 but it is cumbersome having to write ``©this.©'' many times in a member.
     912but it is cumbersome having to write "©this.©" many times in a member.
    934913
    935914\CFA provides a ©with© clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elided the "©this.©" by opening a scope containing field identifiers, changing the qualified fields into variables and giving an opportunity for optimizing qualified references.
    936915\begin{cfa}
    937 int mem( S & this ) ®with this® { §\C{// with clause}§
    938         i = 1;                                          §\C{\color{red}// this.i}§
    939         j = 2;                                          §\C{\color{red}// this.j}§
     916int mem( S &this ) ®with this® { §\C{// with clause}§
     917        i = 1;                                          §\C{\color{red}// this->i}§
     918        j = 2;                                          §\C{\color{red}// this->j}§
    940919}
    941920\end{cfa}
     
    943922\begin{cfa}
    944923struct T { double m, n; };
    945 int mem2( S & this1, T & this2 ) ®with this1, this2® {
     924int mem2( S &this1, T &this2 ) ®with this1, this2® {
    946925        i = 1; j = 2;
    947926        m = 1.0; n = 2.0;
     
    954933        struct S1 { ... } s1;
    955934        struct S2 { ... } s2;
    956         ®with s1® {                                     §\C{// with statement}§
     935        ®with s1® {                     // with statement
    957936                // access fields of s1 without qualification
    958                 ®with s2® {                             §\C{// nesting}§
     937                ®with s2® {  // nesting
    959938                        // access fields of s1 and s2 without qualification
    960939                }
     
    10661045
    10671046
    1068 \section{Alternative Declarations}
    1069 \label{s:AlternativeDeclarations}
     1047\section{Declarations}
     1048\label{s:Declarations}
    10701049
    10711050C declaration syntax is notoriously confusing and error prone.
    10721051For example, many C programmers are confused by a declaration as simple as:
    1073 \begin{cquote}
     1052\begin{quote2}
    10741053\begin{tabular}{@{}ll@{}}
    10751054\begin{cfa}
     
    10791058\raisebox{-0.75\totalheight}{\input{Cdecl}}
    10801059\end{tabular}
    1081 \end{cquote}
     1060\end{quote2}
    10821061Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers?
    1083 If there is any doubt, it implies \Index{productivity} and \Index{safety} issues even for basic programs.
     1062The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs.
    10841063Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site.
    10851064For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    10861065\begin{cfa}
    1087 int ®(*®f®())[®5®]® {...};                              §\C{// definition}§
    1088  ... ®(*®f®())[®3®]® += 1;                              §\C{// usage}§
     1066int ®(*®f®())[®5®]® {...};                              §\C{definition}§
     1067 ... ®(*®f®())[®3®]® += 1;                              §\C{usage}§
    10891068\end{cfa}
    10901069Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
     
    10951074In the following example, \R{red} is the base type and \B{blue} is qualifiers.
    10961075The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    1097 \begin{cquote}
     1076\begin{quote2}
    10981077\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    10991078\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    11101089\end{cfa}
    11111090\end{tabular}
    1112 \end{cquote}
     1091\end{quote2}
    11131092The only exception is \Index{bit field} specification, which always appear to the right of the base type.
    11141093% Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter.
    11151094However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    11161095For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows:
    1117 \begin{cquote}
     1096\begin{quote2}
    11181097\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    11191098\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    11261105\end{cfa}
    11271106\end{tabular}
    1128 \end{cquote}
     1107\end{quote2}
    11291108The downside of this semantics is the need to separate regular and \Index{pointer} declarations:
    1130 \begin{cquote}
     1109\begin{quote2}
    11311110\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    11321111\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    11411120\end{cfa}
    11421121\end{tabular}
    1143 \end{cquote}
     1122\end{quote2}
    11441123which is \Index{prescribing} a safety benefit.
    11451124Other examples are:
    1146 \begin{cquote}
     1125\begin{quote2}
    11471126\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    11481127\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    11801159\end{cfa}
    11811160\end{tabular}
    1182 \end{cquote}
     1161\end{quote2}
    11831162
    11841163All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
    1185 \begin{cquote}
     1164\begin{quote2}
    11861165\begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    11871166\multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
     
    12011180\end{cfa}
    12021181\end{tabular}
    1203 \end{cquote}
     1182\end{quote2}
    12041183All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier}
    12051184The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg:
    1206 \begin{cquote}
     1185\begin{quote2}
    12071186\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    12081187\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    12221201\end{cfa}
    12231202\end{tabular}
    1224 \end{cquote}
     1203\end{quote2}
    12251204
    12261205The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©:
    1227 \begin{cquote}
     1206\begin{quote2}
    12281207\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    12291208\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    12301209\begin{cfa}
    1231 y = (* int)x;
    1232 i = sizeof([ 5 ] * int);
     1210y = (®* int®)x;
     1211i = sizeof(®[ 5 ] * int®);
    12331212\end{cfa}
    12341213&
    12351214\begin{cfa}
    1236 y = (int *)x;
    1237 i = sizeof(int * [ 5 ]);
     1215y = (®int *®)x;
     1216i = sizeof(®int * [ 5 ]®);
    12381217\end{cfa}
    12391218\end{tabular}
    1240 \end{cquote}
     1219\end{quote2}
    12411220
    12421221Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    12431222Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1244 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
     1223Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems.
     1224
     1225
     1226\section{Exponentiation Operator}
     1227
     1228C, \CC, and Java (and many other programming languages) have no exponentiation operator\index{exponentiation!operator}\index{operator!exponentiation}, \ie $x^y$, and instead use a routine, like \Indexc{pow}, to perform the exponentiation operation.
     1229\CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@\lstinline$?\?$} and ©?\=?©\index{?\\=?@\lstinline$?\=?$}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$.
     1230The priority of the exponentiation operator is between the cast and multiplicative operators, so that ©w * (int)x \ (int)y * z© is parenthesized as ©((w * (((int)x) \ ((int)y))) * z)©.
     1231
     1232As for \Index{division}, there are exponentiation operators for integral and floating-point types, including the builtin \Index{complex} types.
     1233Unsigned integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is optimized to $O(\log y)$.} (or shifting if the base is 2).
     1234Signed integral exponentiation\index{exponentiation!signed integral} is performed with repeated multiplication (or shifting if the base is 2), but yields a floating-point result because $x^{-y}=1/x^y$.
     1235Hence, it is important to designate exponent integral-constants as unsigned or signed: ©3 \ 3u© return an integral result, while ©3 \ 3© returns a floating-point result.
     1236Floating-point exponentiation\index{exponentiation!floating point} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
     1237\begin{cfa}
     1238sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
     1239256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     1240\end{cfa}
     1241Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
     1242The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
     1243For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
     1244for returning a floating-point value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents.
    12451245
    12461246
     
    12601260A program \newterm{object} is a region of data storage in the execution environment, the contents of which can represent values.
    12611261In most cases, objects are located in memory at an address, and the variable name for an object is an implicit address to the object generated by the compiler and automatically dereferenced, as in:
    1262 \begin{cquote}
     1262\begin{quote2}
    12631263\begin{tabular}{@{}ll@{\hspace{2em}}l@{}}
    12641264\begin{cfa}
     
    12781278\end{cfa}
    12791279\end{tabular}
    1280 \end{cquote}
     1280\end{quote2}
    12811281where the right example is how the compiler logically interprets the variables in the left example.
    12821282Since a variable name only points to one address during its lifetime, it is an \Index{immutable} \Index{pointer};
     
    12841284In general, variable addresses are stored in instructions instead of loaded from memory, and hence may not occupy storage.
    12851285These approaches are contrasted in the following:
    1286 \begin{cquote}
     1286\begin{quote2}
    12871287\begin{tabular}{@{}l|l@{}}
    12881288\multicolumn{1}{c|}{explicit variable address} & \multicolumn{1}{c}{implicit variable address} \\
     
    13021302\end{cfa}
    13031303\end{tabular}
    1304 \end{cquote}
     1304\end{quote2}
    13051305Finally, the immutable nature of a variable's address and the fact that there is no storage for the variable pointer means pointer assignment\index{pointer!assignment}\index{assignment!pointer} is impossible.
    13061306Therefore, the expression ©x = y© has only one meaning, ©*x = *y©, \ie manipulate values, which is why explicitly writing the dereferences is unnecessary even though it occurs implicitly as part of \Index{instruction decoding}.
     
    13091309(Similarly, an integer variable can contain multiple integer literals during its lifetime versus an integer constant representing a single literal during its lifetime, and like a variable name, may not occupy storage if the literal is embedded directly into instructions.)
    13101310Hence, a pointer occupies memory to store its current address, and the pointer's value is loaded by dereferencing, \eg:
    1311 \begin{cquote}
     1311\begin{quote2}
    13121312\begin{tabular}{@{}l@{\hspace{2em}}l@{}}
    13131313\begin{cfa}
     
    13211321\raisebox{-0.5\totalheight}{\input{pointer2.pstex_t}}
    13221322\end{tabular}
    1323 \end{cquote}
     1323\end{quote2}
    13241324
    13251325Notice, an address has a \Index{duality}\index{address!duality}: a location in memory or the value at that location.
     
    14261426The position of the ©const© qualifier \emph{after} the pointer/reference qualifier causes confuse for C programmers.
    14271427The ©const© qualifier cannot be moved before the pointer/reference qualifier for C style-declarations;
    1428 \CFA-style declarations (see \VRef{s:AlternativeDeclarations}) attempt to address this issue:
    1429 \begin{cquote}
     1428\CFA-style declarations (see \VRef{s:Declarations}) attempt to address this issue:
     1429\begin{quote2}
    14301430\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    14311431\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    14401440\end{cfa}
    14411441\end{tabular}
    1442 \end{cquote}
     1442\end{quote2}
    14431443where the \CFA declaration is read left-to-right.
    14441444
     
    15181518\begin{cfa}
    15191519void f( int i );
    1520 void (* fp)( int );                                     §\C{// routine pointer}§
     1520void (*fp)( int );                                      §\C{// routine pointer}§
    15211521fp = f;                                                         §\C{// reference initialization}§
    15221522fp = &f;                                                        §\C{// pointer initialization}§
     
    18971897\end{cfa}
    18981898This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1899 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:AlternativeDeclarations}), \eg:
     1899Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
    19001900\begin{cfa}
    19011901C :             const double bar1(), bar2( int ), bar3( double );
     
    20722072Default arguments and overloading (see Section 24) are complementary.
    20732073While in theory default arguments can be simulated with overloading, as in:
    2074 \begin{cquote}
     2074\begin{quote2}
    20752075\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    20762076\multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}}   & \multicolumn{1}{c}{\textbf{overloading}}      \\
     
    20872087\end{cfa}
    20882088\end{tabular}
    2089 \end{cquote}
     2089\end{quote2}
    20902090the number of required overloaded routines is linear in the number of default values, which is unacceptable growth.
    20912091In general, overloading should only be used over default arguments if the body of the routine is significantly different.
     
    22242224The following program in undefined in \CFA (and Indexc{gcc})
    22252225\begin{cfa}
    2226 [* [int]( int )] foo() {                §\C{// int (* foo())( int )}§
     2226[* [int]( int )] foo() {                §\C{// int (*foo())( int )}§
    22272227        int ®i® = 7;
    22282228        int bar( int p ) {
     
    22332233}
    22342234int main() {
    2235         * [int]( int ) fp = foo();      §\C{// int (* fp)( int )}§
     2235        * [int]( int ) fp = foo();      §\C{// int (*fp)( int )}§
    22362236        sout | fp( 3 ) | endl;
    22372237}
     
    22722272In the latter approach, additional return values are passed as pointer parameters.
    22732273A pointer parameter is assigned inside the routine to emulate a return.
    2274 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value.
     2274For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating-point value.
    22752275\begin{cfa}
    22762276double modf( double x, double * i );            §\C{// from include math.h}§
     
    29952995
    29962996The common case is printing out a sequence of variables separated by whitespace.
    2997 \begin{cquote}
     2997\begin{quote2}
    29982998\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    29992999\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{\CC}}      \\
     
    30163016\end{cfa}
    30173017\end{tabular}
    3018 \end{cquote}
     3018\end{quote2}
    30193019The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
    30203020Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
     
    30283028Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
    30293029Therefore, fewer output expressions require parenthesis.
    3030 \begin{cquote}
     3030\begin{quote2}
    30313031\begin{tabular}{@{}ll@{}}
    30323032\textbf{\CFA:}
     
    30473047\end{cfa}
    30483048\end{tabular}
    3049 \end{cquote}
     3049\end{quote2}
    30503050There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    30513051
     
    34203420        int id;
    34213421        float size;
    3422         Parts * optionalParts;
     3422        Parts *optionalParts;
    34233423};
    34243424
     
    36343634
    36353635Auto type-inferencing occurs in a declaration where a variable's type is inferred from its initialization ex\-pression type.
    3636 \begin{cquote}
     3636\begin{quote2}
    36373637\begin{tabular}{@{}l@{\hspace{3em}}ll@{}}
    36383638\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{\Indexc{gcc}}} \\
     
    36583658\end{cfa}
    36593659\end{tabular}
    3660 \end{cquote}
     3660\end{quote2}
    36613661The two important capabilities are:
    36623662\begin{itemize}
     
    38063806
    38073807generic(type T)
    3808 typedef int (* predicate)(T);
     3808typedef int (*predicate)(T);
    38093809generic(type Captured, type T)
    3810 typedef void (* callback)(Captured, T);
     3810typedef void (*callback)(Captured, T);
    38113811
    38123812generic(type T)
    3813 void find(int length, T * array,
     3813void find(int length, T *array,
    38143814        predicate(T) p, callback(void *, T)f) {
    38153815        int i;
     
    38353835struct LinkedListElem {
    38363836        T elem;
    3837         LinkedListElem(T) * next;
     3837        LinkedListElem(T) *next;
    38383838};
    38393839
    3840 LinkedListElem *++?(LinkedListElem ** elem) {
    3841         return * elem = elem->next;
     3840LinkedListElem *++?(LinkedListElem **elem) {
     3841        return *elem = elem->next;
    38423842}
    38433843
    38443844generic (type T)
    38453845struct LinkedList {
    3846         LinkedListElem(T) * head;
     3846        LinkedListElem(T) *head;
    38473847        unsigned int size;
    38483848}
    38493849
    38503850generic (type T | bool ?==?(T, T))
    3851 bool contains(LinkedList(T) * list, T elem) {
    3852         for(LinkedListElem * iter = list->head; iter != 0; ++iter) {
     3851bool contains(LinkedList(T) *list, T elem) {
     3852        for(LinkedListElem *iter = list->head; iter != 0; ++iter) {
    38533853        if (iter->elem == elem) return true;
    38543854        }
     
    40634063// transferring requires mutual exclusion and calls deleteJob
    40644064
    4065 void transferJob(mutex Worker & from, Worker & to) {
     4065void transferJob(mutex Worker &from, Worker &to) {
    40664066        ...
    40674067        deleteJob(j);
     
    50015001#include <unistd.h>
    50025002}
    5003 size_t fileSize( const char * path ) {
     5003size_t fileSize( const char *path ) {
    50045004        struct stat s;
    50055005        stat(path, &s);
     
    50385038#[link(name = "libc")]
    50395039extern {
    5040         fn stat(path: * const u8,
    5041         buf: * mut stat_t) -> c_int;
    5042 }
    5043 fn fileSize(path: * const u8) -> size_t
     5040        fn stat(path: *const u8,
     5041        buf: *mut stat_t) -> c_int;
     5042}
     5043fn fileSize(path: *const u8) -> size_t
    50445044{
    50455045        unsafe {
     
    50635063generic(type T, type N |
    50645064        { int ?<?(N, N); })
    5065 T * maximize(N (*f)(const T&),
     5065T *maximize(N (*f)(const T&),
    50665066        int n, T *a) {
    5067         T * bestX = NULL;
     5067        T *bestX = NULL;
    50685068        N bestN;
    50695069        for (int i = 0; i < n; i++) {
     
    50775077}
    50785078
    5079 string * longest(int n, string *p)
     5079string *longest(int n, string *p)
    50805080{
    50815081        return maximize(length, n, p);
     
    50855085\begin{cfa}
    50865086template<typename T, typename F>
    5087 T * maximize(const F &f,
     5087T *maximize(const F &f,
    50885088        int n, T *a) {
    50895089        typedef decltype(f(a[0])) N;
    5090         T * bestX = NULL;
     5090        T *bestX = NULL;
    50915091        N bestN;
    50925092        for (int i = 0; i < n; i++) {
     
    51005100}
    51015101
    5102 string * longest(int n, string *p) {
     5102string *longest(int n, string *p) {
    51035103        return maximize(
    51045104        [](const string &s) {
     
    52585258\begin{cfa}
    52595259task Nonzero {
    5260         int * data;
     5260        int *data;
    52615261        int start;
    52625262        int end;
     
    57215721\CFA introduces the following new keywords.
    57225722
    5723 \begin{cquote}
     5723\begin{quote2}
    57245724\input{../refrat/keywords}
    5725 \end{cquote}
     5725\end{quote2}
    57265726
    57275727
     
    57305730
    57315731\Celeven prescribes the following standard header-files~\cite[\S~7.1.2]{C11} and \CFA adds to this list:
    5732 \begin{cquote}
     5732\begin{quote2}
    57335733\begin{tabular}{@{}llllll|l@{}}
    57345734\multicolumn{6}{c|}{C11} & \multicolumn{1}{c}{\CFA}             \\
     
    57905790\end{tabular}
    57915791\end{tabular}
    5792 \end{cquote}
     5792\end{quote2}
    57935793For the prescribed head-files, \CFA uses header interposition to wraps these includes in an ©extern "C"©;
    57945794hence, names in these include files are not mangled\index{mangling!name} (see~\VRef{s:Interoperability}).
     
    65316531The following factorial programs contrast using GMP with the \CFA and C interfaces, where the output from these programs appears in \VRef[Figure]{f:MultiPrecisionFactorials}.
    65326532(Compile with flag \Indexc{-lgmp} to link with the GMP library.)
    6533 \begin{cquote}
     6533\begin{quote2}
    65346534\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
    65356535\multicolumn{1}{c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     
    65636563\end{cfa}
    65646564\end{tabular}
    6565 \end{cquote}
     6565\end{quote2}
    65666566
    65676567\begin{figure}
  • src/CodeGen/FixMain.cc

    r7c782af rc71b256  
    3939        {
    4040                if(main_signature) {
    41                         throw SemanticError(functionDecl, "Multiple definition of main routine\n");
     41                        throw SemanticError("Multiple definition of main routine\n", functionDecl);
    4242                }
    4343                main_signature.reset( functionDecl->clone() );
  • src/CodeGen/FixNames.cc

    r7c782af rc71b256  
    118118                        int nargs = functionDecl->get_functionType()->get_parameters().size();
    119119                        if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
    120                                 throw SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
     120                                throw SemanticError("Main expected to have 0, 2 or 3 arguments\n", functionDecl);
    121121                        }
    122122                        functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
  • src/Common/PassVisitor.impl.h

    r7c782af rc71b256  
    7777                        maybeAccept_impl( *i, visitor );
    7878                } catch( SemanticError &e ) {
     79                        e.set_location( (*i)->location );
    7980                        errors.append( e );
    8081                }
     
    103104                        maybeMutate_impl( *i, mutator );
    104105                } catch( SemanticError &e ) {
     106                        e.set_location( (*i)->location );
    105107                        errors.append( e );
    106108                }
     
    132134                        }
    133135                } catch( SemanticError &e ) {
     136                        e.set_location( (*i)->location );
    134137                        errors.append( e );
    135138                }
     
    160163                        } // if
    161164                } catch( SemanticError &e ) {
     165                        e.set_location( (*i)->location );
    162166                        errors.append( e );
    163167                } // try
     
    196200
    197201                } catch ( SemanticError &e ) {
     202                        e.set_location( (*i)->location );
    198203                        errors.append( e );
    199204                }
  • src/Common/SemanticError.cc

    r7c782af rc71b256  
    2323#include "SemanticError.h"
    2424
    25 SemanticError::SemanticError( CodeLocation location, std::string error ) {
    26         append( location, error );
     25SemanticError::SemanticError() {
     26}
     27
     28SemanticError::SemanticError( std::string error ) {
     29        append( error );
    2730}
    2831
     
    3134}
    3235
    33 void SemanticError::append( CodeLocation location, const std::string & msg ) {
    34         errors.emplace_back( location, msg );
     36void SemanticError::append( const std::string & msg ) {
     37        errors.emplace_back( error_str() + msg );
    3538}
    3639
     
    3942}
    4043
    41 void SemanticError::print() {
     44void SemanticError::print( std::ostream &os ) {
    4245        using std::to_string;
    4346        for( auto err : errors ) {
    44                 std::cerr << bold() << err.location << error_str() << reset_font() << err.description << std::endl;
     47                os << err.location << err.description << std::endl;
    4548        }
    4649}
    4750
    48 SemanticWarning::SemanticWarning( CodeLocation location, std::string msg ) {
    49         std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl;
     51void SemanticError::set_location( const CodeLocation& location ) {
     52        errors.begin()->maybeSet( location );
    5053}
    5154
  • src/Common/SemanticError.h

    r7c782af rc71b256  
    2424#include "CodeLocation.h"                                                               // for CodeLocation, toString
    2525
    26 //-----------------------------------------------------------------------------
    27 // Errors
    2826struct error {
     27        std::string description;
    2928        CodeLocation location;
    30         std::string description;
    3129
    3230        error() = default;
    33         error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {}
     31        error( const std::string & str ) : description( str ) {}
     32
     33        void maybeSet( const CodeLocation & location ) {
     34                if( this->location.isUnset() ) {
     35                        this->location = location;
     36                }
     37        }
    3438};
    3539
    3640class SemanticError : public std::exception {
    3741  public:
    38         SemanticError() = default;
    39         SemanticError( CodeLocation location, std::string error );
     42        SemanticError();
     43        SemanticError( std::string error );
     44        template< typename T > SemanticError( const std::string & error, const T * obj );
    4045        ~SemanticError() throw() {}
    41 
    42         // constructs an exception using the given message and the printed representation of the obj (T must have a print method)
    43         template< typename T > SemanticError(const T * obj, const std::string & error);
    44         template< typename T > SemanticError( CodeLocation location, const T * obj, const std::string & error);
    4546
    4647        static inline const std::string & error_str() {
     
    5051
    5152        void append( SemanticError & other );
    52         void append( CodeLocation location, const std::string & );
     53        void append( const std::string & );
    5354        bool isEmpty() const;
    54         void print();
     55        void print( std::ostream & os );
     56
     57        void set_location( const CodeLocation & location );
     58        // constructs an exception using the given message and the printed representation of the obj (T must have a print
     59        // method)
    5560  private:
    5661        std::list< error > errors;
     
    5863
    5964template< typename T >
    60 SemanticError::SemanticError( const T * obj, const std::string & error )
    61         : SemanticError( obj->location, toString( error, obj ) )
    62 {}
    63 
    64 template< typename T >
    65 SemanticError::SemanticError( CodeLocation location, const T * obj, const std::string & error )
    66         : SemanticError( location, toString( error, obj ) )
    67 {}
    68 
    69 //-----------------------------------------------------------------------------
    70 // Warnings
    71 class SemanticWarning {
    72   public:
    73         SemanticWarning( CodeLocation location, std::string error );
    74         ~SemanticWarning() throw() {}
    75 
    76         // constructs an exception using the given message and the printed representation of the obj (T must have a print method)
    77         template< typename T > SemanticWarning(const T * obj, const std::string & error);
    78         template< typename T > SemanticWarning( CodeLocation location, const T * obj, const std::string & error);
    79 
    80         static inline const std::string & warning_str() {
    81                 static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: ";
    82                 return str;
    83         }
    84 
    85   private:
    86 };
    87 
    88 template< typename T >
    89 SemanticWarning::SemanticWarning( const T * obj, const std::string & error )
    90         : SemanticWarning( obj->location, toString( error, obj ) )
    91 {}
    92 
    93 template< typename T >
    94 SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error )
    95         : SemanticWarning( location, toString( error, obj ) )
    96 {}
    97 
    98 //-----------------------------------------------------------------------------
    99 // Helpers
    100 static inline const std::string & bold_ttycode() {
    101         static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
    102         return str;
    103 }
    104 
    105 static inline const std::string & reset_font_ttycode() {
    106         static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : "";
    107         return str;
    108 }
    109 
    110 static inline std::string make_bold( const std::string & str ) {
    111         return bold_ttycode() + str + reset_font_ttycode();
    112 }
    113 
    114 struct bold {};
    115 static inline std::ostream & operator<<(std::ostream & os, bold) {
    116         os << bold_ttycode();
    117         return os;
    118 }
    119 
    120 struct reset_font {};
    121 static inline std::ostream & operator<<(std::ostream & os, reset_font) {
    122         os << reset_font_ttycode();
    123         return os;
     65SemanticError::SemanticError( const std::string & error, const T * obj ) {
     66        append( toString( error, obj ) );
    12467}
    12568
  • src/Concurrency/Keywords.cc

    r7c782af rc71b256  
    276276                        handle( decl );
    277277                }
     278
    278279        }
    279280
     
    281282                if( ! decl->body ) return;
    282283
    283                 if( !type_decl ) throw SemanticError( decl, context_error );
     284                if( !type_decl ) throw SemanticError( context_error, decl );
    284285
    285286                FunctionDecl * func = forwardDeclare( decl );
     
    418419                if( mutexArgs.empty() ) return;
    419420
    420                 if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters" );
     421                if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
    421422
    422423                bool isDtor = CodeGen::isDestructor( decl->name );
    423424
    424                 if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument" );
     425                if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
    425426
    426427                for(auto arg : mutexArgs) {
     
    431432                if( ! body ) return;
    432433
    433                 if( !monitor_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
    434                 if( !guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
    435                 if( !dtor_guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
     434                if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
     435                if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
     436                if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
    436437
    437438                if( isDtor ) {
     
    479480                //Makes sure it's not a copy
    480481                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
    481                 if( ! rty ) throw SemanticError( arg, "Mutex argument must be of reference type " );
     482                if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg );
    482483
    483484                //Make sure the we are pointing directly to a type
    484485                Type* base = rty->get_base();
    485                 if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
    486                 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
     486                if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
     487                if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
    487488
    488489                //Make sure that typed isn't mutex
    489                 if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument " );
     490                if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
    490491        }
    491492
     
    625626                if( type && type->get_baseStruct()->is_thread() ) {
    626627                        if( !thread_decl || !thread_ctor_seen ) {
    627                                 throw SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
     628                                throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
    628629                        }
    629630
  • src/Concurrency/Waitfor.cc

    r7c782af rc71b256  
    249249
    250250        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    251                 if( !decl_monitor || !decl_acceptable || !decl_mask )
    252                         throw SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
     251                if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
    253252
    254253                CompoundStmt * stmt = new CompoundStmt();
  • src/ControlStruct/ExceptTranslate.cc

    r7c782af rc71b256  
    572572                        // Pass.
    573573                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    574                         throw SemanticError(catchStmt->location, "catch must have exception type");
     574                        throw SemanticError("catch must have exception type");
    575575                } else {
    576                         throw SemanticError(catchStmt->location, "catchResume must have exception type");
     576                        throw SemanticError("catchResume must have exception type");
    577577                }
    578578
  • src/ControlStruct/LabelFixer.cc

    r7c782af rc71b256  
    9292                        } else if ( labelTable[ l ]->defined() ) {
    9393                                // defined twice, error
    94                                 throw SemanticError( l.get_statement()->location, "Duplicate definition of label: " + l.get_name() );
     94                                throw SemanticError( "Duplicate definition of label: " + l.get_name() );
    9595                        }       else {
    9696                                // used previously, but undefined until now -> link with this entry
     
    121121                for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
    122122                        if ( ! i->second->defined() ) {
    123                                 throw SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
     123                                throw SemanticError( "Use of undefined label: " + i->first.get_name() );
    124124                        }
    125125                        (*ret)[ i->first ] = i->second->get_definition();
  • src/ControlStruct/MLEMutator.cc

    r7c782af rc71b256  
    115115                                        } else {
    116116                                                // break target is outmost control structure
    117                                                 if ( enclosingControlStructures.empty() ) throw SemanticError( branchStmt->location, "'break' outside a loop, switch, or labelled block" );
     117                                                if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
    118118                                                targetEntry = enclosingControlStructures.rbegin();
    119119                                        } // if
     
    124124                                // ensure that selected target is valid
    125125                                if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
    126                                         throw SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
     126                                        throw SemanticError( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
    127127                                } // if
    128128                                break;
  • src/GenPoly/Box.cc

    r7c782af rc71b256  
    229229                                } // if
    230230                        } catch( SemanticError &e ) {
     231                                e.set_location( (*i)->location );
    231232                                errors.append( e );
    232233                        } // try
     
    575576                                                }
    576577                                        } else {
    577                                                 throw SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
     578                                                throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
    578579                                        }
    579580                                }
     
    597598                                        } else {
    598599                                                // xxx - should this be an assertion?
    599                                                 throw SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
     600                                                throw SemanticError( toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ), appExpr );
    600601                                        } // if
    601602                                } // if
  • src/InitTweak/FixInit.cc

    r7c782af rc71b256  
    282282                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    283283                                } catch( SemanticError &e ) {
     284                                        e.set_location( (*i)->location );
    284285                                        errors.append( e );
    285286                                } // try
     
    894895                        )
    895896                        if ( ! diff.empty() ) {
    896                                 throw SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
     897                                throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
    897898                        } // if
    898899                        // S_G-S_L results in set of objects that must be destructed
     
    11101111                template< typename Visitor, typename... Params >
    11111112                void error( Visitor & v, CodeLocation loc, const Params &... params ) {
    1112                         SemanticError err( loc, toString( params... ) );
     1113                        SemanticError err( toString( params... ) );
     1114                        err.set_location( loc );
    11131115                        v.errors.append( err );
    11141116                }
  • src/InitTweak/GenInit.cc

    r7c782af rc71b256  
    317317                if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    318318                        // constructed objects cannot be designated
    319                         if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
     319                        if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
    320320                        // constructed objects should not have initializers nested too deeply
    321                         if ( ! checkInitDepth( objDecl ) ) throw SemanticError( objDecl, "Managed object's initializer is too deep " );
     321                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
    322322
    323323                        objDecl->set_init( genCtorInit( objDecl ) );
  • src/InitTweak/InitTweak.cc

    r7c782af rc71b256  
    225225                                        // xxx - this shouldn't be an error, but need a way to
    226226                                        // terminate without creating output, so should catch this error
    227                                         throw SemanticError( init->location, "unbalanced list initializers" );
     227                                        throw SemanticError( "unbalanced list initializers" );
    228228                                }
    229229
  • src/Parser/DeclarationNode.cc

    r7c782af rc71b256  
    581581                                        dst->basictype = src->basictype;
    582582                                } else if ( src->basictype != DeclarationNode::NoBasicType )
    583                                         throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " );
     583                                        throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ", src );
    584584
    585585                                if ( dst->complextype == DeclarationNode::NoComplexType ) {
    586586                                        dst->complextype = src->complextype;
    587587                                } else if ( src->complextype != DeclarationNode::NoComplexType )
    588                                         throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " );
     588                                        throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ", src );
    589589
    590590                                if ( dst->signedness == DeclarationNode::NoSignedness ) {
    591591                                        dst->signedness = src->signedness;
    592592                                } else if ( src->signedness != DeclarationNode::NoSignedness )
    593                                         throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
     593                                        throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ", src );
    594594
    595595                                if ( dst->length == DeclarationNode::NoLength ) {
     
    598598                                        dst->length = DeclarationNode::LongLong;
    599599                                } else if ( src->length != DeclarationNode::NoLength )
    600                                         throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
     600                                        throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ", src );
    601601                        } // if
    602602                        break;
     
    966966                        } // if
    967967                } catch( SemanticError &e ) {
     968                        e.set_location( cur->location );
    968969                        errors.append( e );
    969970                } // try
     
    10001001                        } // if
    10011002                } catch( SemanticError &e ) {
     1003                        e.set_location( cur->location );
    10021004                        errors.append( e );
    10031005                } // try
     
    10181020                        * out++ = cur->buildType();
    10191021                } catch( SemanticError &e ) {
     1022                        e.set_location( cur->location );
    10201023                        errors.append( e );
    10211024                } // try
     
    10291032
    10301033Declaration * DeclarationNode::build() const {
    1031         if ( ! error.empty() ) throw SemanticError( this, error + " in declaration of " );
     1034        if ( ! error.empty() ) throw SemanticError( error + " in declaration of ", this );
    10321035
    10331036        if ( asmStmt ) {
     
    10521055                //    inline _Noreturn int i;                   // disallowed
    10531056                if ( type->kind != TypeData::Function && funcSpecs.any() ) {
    1054                         throw SemanticError( this, "invalid function specifier for " );
     1057                        throw SemanticError( "invalid function specifier for ", this );
    10551058                } // if
    10561059                return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
     
    10621065        //    inlne _Noreturn enum   E { ... };         // disallowed
    10631066        if ( funcSpecs.any() ) {
    1064                 throw SemanticError( this, "invalid function specifier for " );
     1067                throw SemanticError( "invalid function specifier for ", this );
    10651068        } // if
    10661069        assertf( name, "ObjectDecl must a have name\n" );
  • src/Parser/ExpressionNode.cc

    r7c782af rc71b256  
    356356
    357357Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
    358         if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( yylloc, "invalid tuple index " + str );
     358        if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( "invalid tuple index " + str );
    359359        Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
    360360        delete &str;
     
    363363
    364364Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
    365         if ( str[str.size()-1] != '.' ) throw SemanticError( yylloc, "invalid tuple index " + str );
     365        if ( str[str.size()-1] != '.' ) throw SemanticError( "invalid tuple index " + str );
    366366        Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
    367367        delete &str;
  • src/Parser/LinkageSpec.cc

    r7c782af rc71b256  
    2424namespace LinkageSpec {
    2525
    26 Spec linkageCheck( CodeLocation location, const string * spec ) {
     26Spec linkageCheck( const string * spec ) {
    2727        assert( spec );
    2828        unique_ptr<const string> guard( spec ); // allocated by lexer
     
    3434                return BuiltinC;
    3535        } else {
    36                 throw SemanticError( location, "Invalid linkage specifier " + *spec );
     36                throw SemanticError( "Invalid linkage specifier " + *spec );
    3737        } // if
    3838}
    3939
    40 Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
     40Spec linkageUpdate( Spec old_spec, const string * cmd ) {
    4141        assert( cmd );
    4242        unique_ptr<const string> guard( cmd ); // allocated by lexer
     
    4848                return old_spec;
    4949        } else {
    50                 throw SemanticError( location, "Invalid linkage specifier " + *cmd );
     50                throw SemanticError( "Invalid linkage specifier " + *cmd );
    5151        } // if
    5252}
  • src/Parser/LinkageSpec.h

    r7c782af rc71b256  
    1717
    1818#include <string>
    19 
    20 #include "Common/CodeLocation.h"
    2119
    2220namespace LinkageSpec {
     
    4745
    4846
    49         Spec linkageCheck( CodeLocation location, const std::string * );
     47        Spec linkageCheck( const std::string * );
    5048        // Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
    51         Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
     49        Spec linkageUpdate( Spec old_spec, const std::string * cmd );
    5250        /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
    5351         * If cmd = "Cforall" returns old_spec Spec with is_mangled = true
  • src/Parser/ParseNode.h

    r7c782af rc71b256  
    434434                        } // if
    435435                } catch( SemanticError &e ) {
     436                        e.set_location( cur->location );
    436437                        errors.append( e );
    437438                } // try
  • src/Parser/TypeData.cc

    r7c782af rc71b256  
    3131using namespace std;
    3232
    33 TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
     33TypeData::TypeData( Kind k ) : kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
    3434        switch ( kind ) {
    3535          case Unknown:
     
    521521
    522522static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
    523         throw SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
     523        throw SemanticError( string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
    524524} // genTSError
    525525
     
    800800        assert( td->base );
    801801        if ( td->symbolic.isTypedef ) {
    802                 ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage );
     802                ret = new TypedefDecl( name, scs, typebuild( td->base ), linkage );
    803803        } else {
    804804                ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true );
     
    923923                                // type set => parameter name already transformed by a declaration names so there is a duplicate
    924924                                // declaration name attempting a second transformation
    925                                 if ( param->type ) throw SemanticError( param->location, string( "duplicate declaration name " ) + *param->name );
     925                                if ( param->type ) throw SemanticError( string( "duplicate declaration name " ) + *param->name );
    926926                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
    927927                                // parameter name attempting a second transformation
    928                                 if ( ! decl->type ) throw SemanticError( param->location, string( "duplicate parameter name " ) + *param->name );
     928                                if ( ! decl->type ) throw SemanticError( string( "duplicate parameter name " ) + *param->name );
    929929                                param->type = decl->type;                               // set copy declaration type to parameter type
    930930                                decl->type = nullptr;                                   // reset declaration type
     
    933933                } // for
    934934                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
    935                 if ( decl->type ) throw SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
     935                if ( decl->type ) throw SemanticError( string( "missing name in parameter list " ) + *decl->name );
    936936        } // for
    937937
  • src/Parser/TypeData.h

    r7c782af rc71b256  
    7676        };
    7777
    78         CodeLocation location;
    79 
    8078        Kind kind;
    8179        TypeData * base;
  • src/Parser/parser.yy

    r7c782af rc71b256  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 15 17:12:31 2018
    13 // Update Count     : 3006
     12// Last Modified On : Thu Dec 21 11:32:56 2017
     13// Update Count     : 2996
    1414//
    1515
     
    482482                { $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); }
    483483        | type_name '.' no_attr_identifier                                      // CFA, nested type
    484                 { throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
     484                { throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; }                                                          // FIX ME
    485485        | type_name '.' '[' push field_list pop ']'                     // CFA, nested type / tuple field selector
    486                 { throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
    487         | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    488                 { throw SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; } // FIX ME
    489         ;
    490 
    491 generic_assoc_list:                                                                             // C11
    492         | generic_association
    493         | generic_assoc_list ',' generic_association
    494         ;
    495 
    496 generic_association:                                                                    // C11
    497         type_no_function ':' assignment_expression
    498         | DEFAULT ':' assignment_expression
     486                { throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; }                                                          // FIX ME
    499487        ;
    500488
     
    779767        | unary_expression assignment_operator assignment_expression
    780768                { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); }
    781         | unary_expression '=' '{' initializer_list comma_opt '}' // FIX ME
    782                 { $$ = nullptr; }
    783769        ;
    784770
     
    10641050        | RETURN comma_expression_opt ';'
    10651051                { $$ = new StatementNode( build_return( $2 ) ); }
    1066         | RETURN '{' initializer_list comma_opt '}'                     // FIX ME
    1067                 { $$ = nullptr; }
    10681052        | THROW assignment_expression_opt ';'                           // handles rethrow
    10691053                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    10841068mutex_statement:
    10851069        MUTEX '(' argument_expression_list ')' statement
    1086                 { throw SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
     1070                { throw SemanticError("Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME
    10871071        ;
    10881072
     
    13051289static_assert:
    13061290        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1307                 { throw SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; }   // FIX ME
     1291                { throw SemanticError("Static assert is currently unimplemented."); $$ = nullptr; }     // FIX ME
    13081292
    13091293// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    23932377                {
    23942378                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    2395                         linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
     2379                        linkage = LinkageSpec::linkageUpdate( linkage, $2 );
    23962380                }
    23972381          '{' external_definition_list_opt '}'
  • src/ResolvExpr/AlternativeFinder.cc

    r7c782af rc71b256  
    239239                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
    240240                        )
    241                         throw SemanticError( expr, "No reasonable alternatives for expression " );
     241                        throw SemanticError( "No reasonable alternatives for expression ", expr );
    242242                }
    243243                if ( prune ) {
     
    257257                                stream << "Alternatives are:\n";
    258258                                printAlts( winners, stream, 1 );
    259                                 throw SemanticError( expr->location, stream.str() );
     259                                throw SemanticError( stream.str() );
    260260                        }
    261261                        alternatives = move(pruned);
     
    494494                                return;
    495495                        } else if ( level >= recursionLimit ) {
    496                                 throw SemanticError( newAlt.expr->location, "Too many recursive assertions" );
     496                                throw SemanticError( "Too many recursive assertions" );
    497497                        } else {
    498498                                AssertionSet newerNeed;
     
    14081408                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    14091409                        if ( winners.size() != 1 ) {
    1410                                 throw SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
     1410                                throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
    14111411                        } // if
    14121412                        // return the lowest cost alternative for the argument
     
    14291429                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    14301430                        if ( winners.size() != 1 ) {
    1431                                 throw SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
     1431                                throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() );
    14321432                        } // if
    14331433                        // return the lowest cost alternative for the argument
  • src/ResolvExpr/CurrentObject.cc

    r7c782af rc71b256  
    141141                        base = at->get_base();
    142142                        memberIter = createMemberIterator( base );
    143                         if ( at->isVarLen ) throw SemanticError( at, "VLA initialization does not support @=" );
     143                        if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at );
    144144                        setSize( at->get_dimension() );
    145145                }
     
    156156                                        PRINT( std::cerr << "array type with size: " << size << std::endl; )
    157157                                } catch ( SemanticError & ) {
    158                                         throw SemanticError( expr, "Constant expression of non-integral type in array dimension: " );
     158                                        throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr );
    159159                                }
    160160                        }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     
    179179                                        index = constExpr->intValue();
    180180                                } catch( SemanticError & ) {
    181                                         throw SemanticError( expr, "Constant expression of non-integral type in array designator: " );
     181                                        throw SemanticError( "Constant expression of non-integral type in array designator: ", expr );
    182182                                }
    183183                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     
    532532                } // for
    533533                if ( desigAlts.size() > 1 ) {
    534                         throw SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
     534                        throw SemanticError( toString("Too many alternatives (", desigAlts.size(), ") for designation: "), designation );
    535535                } else if ( desigAlts.size() == 0 ) {
    536                         throw SemanticError( designation, "No reasonable alternatives for designation: " );
     536                        throw SemanticError( "No reasonable alternatives for designation: ", designation );
    537537                }
    538538                DesignatorChain & d = desigAlts.back();
  • src/ResolvExpr/Resolver.cc

    r7c782af rc71b256  
    174174                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    175175                        if ( winners.size() == 0 ) {
    176                                 throw SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     176                                throw SemanticError( toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: "), untyped );
    177177                        } else if ( winners.size() != 1 ) {
    178178                                std::ostringstream stream;
     
    181181                                stream << "Alternatives are:\n";
    182182                                printAlts( winners, stream, 1 );
    183                                 throw SemanticError( untyped->location, stream.str() );
     183                                throw SemanticError( stream.str() );
    184184                        }
    185185
     
    187187                        Alternative & choice = winners.front();
    188188                        if ( findDeletedExpr( choice.expr ) ) {
    189                                 throw SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
     189                                throw SemanticError( "Unique best alternative includes deleted identifier in ", choice.expr );
    190190                        }
    191191                        alt = std::move( choice );
     
    484484                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    485485                                ss << "' in call to waitfor";
    486                                 throw SemanticError( stmt->location, ss.str() );
     486                                throw SemanticError( ss.str() );
    487487                        }
    488488
     
    506506                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    507507                                        if( !pointer ) {
    508                                                 throw SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
     508                                                throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
    509509                                        }
    510510
    511511                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    512512                                        if( !function ) {
    513                                                 throw SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
     513                                                throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
    514514                                        }
    515515
     
    520520
    521521                                                if( !advance_to_mutex( param, param_end ) ) {
    522                                                         throw SemanticError(function, "candidate function not viable: no mutex parameters\n");
     522                                                        throw SemanticError("candidate function not viable: no mutex parameters\n", function);
    523523                                                }
    524524                                        }
     
    559559                                                                        // We ran out of parameters but still have arguments
    560560                                                                        // this function doesn't match
    561                                                                         throw SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
     561                                                                        throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
    562562                                                                }
    563563
     
    571571                                                                        (*param)->get_type()->print( ss );
    572572                                                                        ss << "'\n";
    573                                                                         throw SemanticError( function, ss.str() );
     573                                                                        throw SemanticError(ss.str(), function);
    574574                                                                }
    575575
     
    583583                                                                // We ran out of arguments but still have parameters left
    584584                                                                // this function doesn't match
    585                                                                 throw SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
     585                                                                throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
    586586                                                        }
    587587
     
    610610
    611611                        // Make sure we got the right number of arguments
    612                         if( func_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    613                         if( args_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    614                         if( func_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    615                         if( args_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     612                        if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     613                        if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     614                        if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     615                        if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    616616                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    617617
  • src/SymTab/Indexer.cc

    r7c782af rc71b256  
    443443                        // isomorphic to C type-compatibility, which it may not be.
    444444                        if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
    445                                 throw SemanticError( decl, "conflicting overload of C function " );
     445                                throw SemanticError( "conflicting overload of C function ", decl );
    446446                        }
    447447                } else {
    448448                        // Check that a Cforall declaration doesn't override any C declaration
    449449                        if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    450                                 throw SemanticError( decl, "Cforall declaration hides C function " );
     450                                throw SemanticError( "Cforall declaration hides C function ", decl );
    451451                        }
    452452                }
     
    463463        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
    464464                // default handling of conflicts is to raise an error
    465                 addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, baseExpr );
     465                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); return true; }, baseExpr );
    466466        }
    467467
    468468        void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
    469469                // default handling of conflicts is to raise an error
    470                 addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
     470                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); return true; }, nullptr, deleteStmt );
    471471        }
    472472
     
    477477                        return true;
    478478                } else {
    479                         throw SemanticError( added, "redeclaration of " );
     479                        throw SemanticError( "redeclaration of ", added );
    480480                }
    481481        }
     
    504504                        return false;
    505505                } else if ( ! added->get_members().empty() ) {
    506                         throw SemanticError( added, "redeclaration of " );
     506                        throw SemanticError( "redeclaration of ", added );
    507507                } // if
    508508                return true;
  • src/SymTab/Validate.cc

    r7c782af rc71b256  
    361361                        // the only case in which "void" is valid is where it is the only one in the list
    362362                        if ( containsVoid && ( nvals > 1 || isVarArgs ) ) {
    363                                 throw SemanticError( func, "invalid type void in function type " );
     363                                throw SemanticError( "invalid type void in function type ", func );
    364364                        }
    365365
     
    402402                for ( Expression * param : inst->parameters ) {
    403403                        if ( ! dynamic_cast< TypeExpr * >( param ) ) {
    404                                 throw SemanticError( inst, "Expression parameters for generic types are currently unsupported: " );
     404                                throw SemanticError( "Expression parameters for generic types are currently unsupported: ", inst );
    405405                        }
    406406                }
     
    502502                TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
    503503                if ( ! traitDecl ) {
    504                         throw SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
     504                        throw SemanticError( "use of undeclared trait " + traitInst->name );
    505505                } // if
    506506                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
    507                         throw SemanticError( traitInst, "incorrect number of trait parameters: " );
     507                        throw SemanticError( "incorrect number of trait parameters: ", traitInst );
    508508                } // if
    509509                traitInst->baseTrait = traitDecl;
     
    513513                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
    514514                        if ( ! expr ) {
    515                                 throw SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
     515                                throw SemanticError( "Expression parameters for trait instances are currently unsupported: ", std::get<1>(p) );
    516516                        }
    517517                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
     
    619619                                bool isVoid = fixFunction( assertion );
    620620                                if ( isVoid ) {
    621                                         throw SemanticError( node, "invalid type void in assertion of function " );
     621                                        throw SemanticError( "invalid type void in assertion of function ", node );
    622622                                } // if
    623623                        } // for
     
    663663                // were cast to void.
    664664                if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) {
    665                         throw SemanticError( returnStmt, "Non-void function returns no values: " );
     665                        throw SemanticError( "Non-void function returns no values: " , returnStmt );
    666666                }
    667667        }
     
    704704                                ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
    705705                                if ( ! rtt ) {
    706                                         throw SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
     706                                        throw SemanticError("Cannot apply type parameters to base type of " + typeInst->name);
    707707                                }
    708708                                rtt->get_parameters().clear();
     
    742742                        Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
    743743                        if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
    744                                 throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
     744                                throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );
    745745                        }
    746746                        // Cannot redefine VLA typedefs. Note: this is slightly incorrect, because our notion of VLAs
     
    749749                        // to fix this corner case likely outweighs the utility of allowing it.
    750750                        if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) {
    751                                 throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
     751                                throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );
    752752                        }
    753753                } else {
     
    847847                                type = new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() );
    848848                        } // if
    849                         TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
     849                        TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), Type::StorageClasses(), type, aggDecl->get_linkage() ) );
    850850                        typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
    851851                } // if
     
    898898                if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
    899899                        if ( params.size() == 0 ) {
    900                                 throw SemanticError( funcDecl, "Constructors, destructors, and assignment functions require at least one parameter " );
     900                                throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
    901901                        }
    902902                        ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
    903903                        if ( ! refType ) {
    904                                 throw SemanticError( funcDecl, "First parameter of a constructor, destructor, or assignment function must be a reference " );
     904                                throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl );
    905905                        }
    906906                        if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
    907                                 throw SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values " );
     907                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
    908908                        }
    909909                }
     
    940940
    941941                        sub.apply( inst );
    942                         if ( args.size() < params->size() ) throw SemanticError( inst, "Too few type arguments in generic type " );
    943                         if ( args.size() > params->size() ) throw SemanticError( inst, "Too many type arguments in generic type " );
     942                        if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst );
     943                        if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst );
    944944                }
    945945        }
  • src/SynTree/Declaration.h

    r7c782af rc71b256  
    245245        typedef NamedTypeDecl Parent;
    246246  public:
    247         TypedefDecl( const std::string &name, CodeLocation location, Type::StorageClasses scs, Type *type, LinkageSpec::Spec spec = LinkageSpec::Cforall )
    248                 : Parent( name, scs, type ) { set_linkage( spec ); this->location = location; }
    249 
     247        TypedefDecl( const std::string &name, Type::StorageClasses scs, Type *type, LinkageSpec::Spec spec = LinkageSpec::Cforall ) : Parent( name, scs, type ) { set_linkage( spec ); }
    250248        TypedefDecl( const TypedefDecl &other ) : Parent( other ) {}
    251249
  • src/SynTree/Expression.cc

    r7c782af rc71b256  
    9393                return 0;
    9494        }
    95         throw SemanticError( this, "Constant expression of non-integral type " );
     95        throw SemanticError( "Constant expression of non-integral type ", this );
    9696}
    9797
  • src/SynTree/Mutator.h

    r7c782af rc71b256  
    149149                        } // if
    150150                } catch( SemanticError &e ) {
     151                        e.set_location( (*i)->location );
    151152                        errors.append( e );
    152153                } // try
  • src/SynTree/Statement.cc

    r7c782af rc71b256  
    100100        //actually this is a syntactic error signaled by the parser
    101101        if ( type == BranchStmt::Goto && target.empty() ) {
    102                 throw SemanticError( target.get_statement()->location, "goto without target");
     102                throw SemanticError("goto without target");
    103103        }
    104104}
     
    107107        Statement(), computedTarget( computedTarget ), type( type ) {
    108108        if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
    109                 throw SemanticError( computedTarget->location, "Computed target not valid in branch statement");
     109                throw SemanticError("Computed target not valid in branch statement");
    110110        }
    111111}
     
    203203CaseStmt::CaseStmt( Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
    204204        Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
    205         if ( isDefault() && condition != 0 ) throw SemanticError( condition, "default case with condition: " );
     205        if ( isDefault() && condition != 0 ) throw SemanticError("default case with condition: ", condition);
    206206}
    207207
  • src/SynTree/TypeSubstitution.h

    r7c782af rc71b256  
    9898                                } // if
    9999                        } else {
    100                                 throw SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
     100                                throw SemanticError( toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ), formal );
    101101                        } // if
    102102                } else {
  • src/SynTree/Visitor.h

    r7c782af rc71b256  
    143143                        }
    144144                } catch( SemanticError &e ) {
     145                        e.set_location( (*i)->location );
    145146                        errors.append( e );
    146147                }
  • src/libcfa/concurrency/alarm.c

    r7c782af rc71b256  
    1818#include <stdio.h>
    1919#include <string.h>
     20#include <time.h>
    2021#include <unistd.h>
    2122#include <sys/time.h>
     
    2627#include "preemption.h"
    2728
    28 
    29 static inline void ?{}( itimerval & this, __cfa_time_t * alarm ) with( this ) {
    30         it_value.tv_sec = alarm->val / (1`cfa_s).val;                   // seconds
    31         it_value.tv_usec = max( (alarm->val % (1`cfa_s).val) / (1`cfa_us).val, 1000 ); // microseconds
     29//=============================================================================================
     30// time type
     31//=============================================================================================
     32
     33#define one_second         1_000_000_000ul
     34#define one_milisecond         1_000_000ul
     35#define one_microsecond            1_000ul
     36#define one_nanosecond                 1ul
     37
     38__cfa_time_t zero_time = { 0 };
     39
     40void ?{}( __cfa_time_t & this ) { this.val = 0; }
     41void ?{}( __cfa_time_t & this, zero_t zero ) { this.val = 0; }
     42
     43void ?{}( itimerval & this, __cfa_time_t * alarm ) with( this ) {
     44        it_value.tv_sec = alarm->val / one_second;                      // seconds
     45        it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds
    3246        it_interval.tv_sec = 0;
    3347        it_interval.tv_usec = 0;
    3448}
    3549
    36 static inline void ?{}( __cfa_time_t & this, timespec * curr ) {
     50
     51void ?{}( __cfa_time_t & this, timespec * curr ) {
    3752        uint64_t secs  = curr->tv_sec;
    3853        uint64_t nsecs = curr->tv_nsec;
    39         this.val = from_s(secs).val + nsecs;
    40 }
     54        this.val = (secs * one_second) + nsecs;
     55}
     56
     57__cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ) {
     58        this.val = 0;
     59        return this;
     60}
     61
     62__cfa_time_t from_s ( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1_000_000_000ul; return ret; }
     63__cfa_time_t from_ms( uint64_t val ) { __cfa_time_t ret; ret.val = val *     1_000_000ul; return ret; }
     64__cfa_time_t from_us( uint64_t val ) { __cfa_time_t ret; ret.val = val *         1_000ul; return ret; }
     65__cfa_time_t from_ns( uint64_t val ) { __cfa_time_t ret; ret.val = val *             1ul; return ret; }
    4166
    4267//=============================================================================================
     
    5984//=============================================================================================
    6085
    61 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) {
     86void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) {
    6287        this.thrd = thrd;
    6388        this.alarm = alarm;
     
    6893}
    6994
    70 void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) {
     95void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) {
    7196        this.proc = proc;
    7297        this.alarm = alarm;
  • src/libcfa/concurrency/alarm.h

    r7c782af rc71b256  
    2121#include <assert.h>
    2222
    23 #include "bits/cfatime.h"
    24 
    2523struct thread_desc;
    2624struct processor;
     25
     26struct timespec;
     27struct itimerval;
     28
     29//=============================================================================================
     30// time type
     31//=============================================================================================
     32
     33struct __cfa_time_t {
     34        uint64_t val;
     35};
     36
     37// ctors
     38void ?{}( __cfa_time_t & this );
     39void ?{}( __cfa_time_t & this, zero_t zero );
     40void ?{}( __cfa_time_t & this, timespec * curr );
     41void ?{}( itimerval & this, __cfa_time_t * alarm );
     42
     43__cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs );
     44
     45// logical ops
     46static inline bool ?==?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val == rhs.val; }
     47static inline bool ?!=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val != rhs.val; }
     48static inline bool ?>? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >  rhs.val; }
     49static inline bool ?<? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <  rhs.val; }
     50static inline bool ?>=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >= rhs.val; }
     51static inline bool ?<=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <= rhs.val; }
     52
     53static inline bool ?==?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val == rhs; }
     54static inline bool ?!=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val != rhs; }
     55static inline bool ?>? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >  rhs; }
     56static inline bool ?<? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <  rhs; }
     57static inline bool ?>=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >= rhs; }
     58static inline bool ?<=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <= rhs; }
     59
     60// addition/substract
     61static inline __cfa_time_t ?+?( __cfa_time_t lhs, __cfa_time_t rhs ) {
     62        __cfa_time_t ret;
     63        ret.val = lhs.val + rhs.val;
     64        return ret;
     65}
     66
     67static inline __cfa_time_t ?-?( __cfa_time_t lhs, __cfa_time_t rhs ) {
     68        __cfa_time_t ret;
     69        ret.val = lhs.val - rhs.val;
     70        return ret;
     71}
     72
     73__cfa_time_t from_s ( uint64_t );
     74__cfa_time_t from_ms( uint64_t );
     75__cfa_time_t from_us( uint64_t );
     76__cfa_time_t from_ns( uint64_t );
     77
     78extern __cfa_time_t zero_time;
    2779
    2880//=============================================================================================
     
    53105typedef alarm_node_t ** __alarm_it_t;
    54106
    55 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s );
    56 void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s );
     107void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
     108void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
    57109void ^?{}( alarm_node_t & this );
    58110
  • src/libcfa/concurrency/coroutine.c

    r7c782af rc71b256  
    9999// Wrapper for co
    100100void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    101         verify( preemption.enabled || this_processor->do_terminate );
    102101        disable_interrupts();
    103102
     
    117116
    118117        enable_interrupts( __cfaabi_dbg_ctx );
    119         verify( preemption.enabled || this_processor->do_terminate );
    120118} //ctxSwitchDirect
    121119
  • src/libcfa/concurrency/invoke.c

    r7c782af rc71b256  
    2828extern void __suspend_internal(void);
    2929extern void __leave_coroutine(void);
    30 extern void __finish_creation(void);
    3130extern void __leave_thread_monitor( struct thread_desc * this );
    3231extern void disable_interrupts();
     
    4544
    4645        cor->state = Active;
    47 
    48         enable_interrupts( __cfaabi_dbg_ctx );
    4946
    5047        main( this );
     
    6562        // First suspend, once the thread arrives here,
    6663        // the function pointer to main can be invalidated without risk
    67         __finish_creation();
     64        __suspend_internal();
    6865
    6966        // Fetch the thread handle from the user defined thread structure
  • src/libcfa/concurrency/kernel.c

    r7c782af rc71b256  
    5656thread_local processor *      volatile this_processor;
    5757
    58 // volatile thread_local bool preemption_in_progress = 0;
    59 // volatile thread_local bool preemption_enabled = false;
    60 // volatile thread_local unsigned short disable_preempt_count = 1;
    61 
    62 volatile thread_local __cfa_kernel_preemption_data_t preemption = { false, false, 1 };
     58volatile thread_local bool preemption_in_progress = 0;
     59volatile thread_local bool preemption_enabled = false;
     60volatile thread_local unsigned short disable_preempt_count = 1;
    6361
    6462//-----------------------------------------------------------------------------
     
    209207                        if(readyThread)
    210208                        {
    211                                 verify( !preemption.enabled );
     209                                verify( !preemption_enabled );
    212210
    213211                                runThread(this, readyThread);
    214212
    215                                 verify( !preemption.enabled );
     213                                verify( !preemption_enabled );
    216214
    217215                                //Some actions need to be taken from the kernel
     
    262260void finishRunning(processor * this) with( this->finish ) {
    263261        if( action_code == Release ) {
    264                 verify( !preemption.enabled );
     262                verify( !preemption_enabled );
    265263                unlock( *lock );
    266264        }
     
    269267        }
    270268        else if( action_code == Release_Schedule ) {
    271                 verify( !preemption.enabled );
     269                verify( !preemption_enabled );
    272270                unlock( *lock );
    273271                ScheduleThread( thrd );
    274272        }
    275273        else if( action_code == Release_Multi ) {
    276                 verify( !preemption.enabled );
     274                verify( !preemption_enabled );
    277275                for(int i = 0; i < lock_count; i++) {
    278276                        unlock( *locks[i] );
     
    306304        this_coroutine = NULL;
    307305        this_thread = NULL;
    308         preemption.enabled = false;
    309         preemption.disable_count = 1;
     306        preemption_enabled = false;
     307        disable_preempt_count = 1;
    310308        // SKULLDUGGERY: We want to create a context for the processor coroutine
    311309        // which is needed for the 2-step context switch. However, there is no reason
     
    347345}
    348346
    349 void kernel_first_resume(processor * this) {
    350         coroutine_desc * src = this_coroutine;
    351         coroutine_desc * dst = get_coroutine(*this->runner);
    352 
    353         verify( !preemption.enabled );
    354 
    355         create_stack(&dst->stack, dst->stack.size);
    356         CtxStart(this->runner, CtxInvokeCoroutine);
    357 
    358         verify( !preemption.enabled );
    359 
    360         dst->last = src;
    361         dst->starter = dst->starter ? dst->starter : src;
    362 
    363         // set state of current coroutine to inactive
    364         src->state = src->state == Halted ? Halted : Inactive;
    365 
    366         // set new coroutine that task is executing
    367         this_coroutine = dst;
    368 
    369         // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
    370         // Therefore, when first creating a coroutine, interrupts are enable before calling the main.
    371         // This is consistent with thread creation. However, when creating the main processor coroutine,
    372         // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will
    373         // stay disabled.
    374         disable_interrupts();
    375 
    376         // context switch to specified coroutine
    377         assert( src->stack.context );
    378         CtxSwitch( src->stack.context, dst->stack.context );
    379         // when CtxSwitch returns we are back in the src coroutine
    380 
    381         // set state of new coroutine to active
    382         src->state = Active;
    383 
    384         verify( !preemption.enabled );
    385 }
    386 
    387347//-----------------------------------------------------------------------------
    388348// Scheduler routines
     
    392352        verify( thrd->self_cor.state != Halted );
    393353
    394         verify( !preemption.enabled );
     354        verify( !preemption_enabled );
    395355
    396356        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
     
    402362        }
    403363
    404         verify( !preemption.enabled );
     364        verify( !preemption_enabled );
    405365}
    406366
    407367thread_desc * nextThread(cluster * this) with( *this ) {
    408         verify( !preemption.enabled );
     368        verify( !preemption_enabled );
    409369        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    410370        thread_desc * head = pop_head( ready_queue );
    411371        unlock( ready_queue_lock );
    412         verify( !preemption.enabled );
     372        verify( !preemption_enabled );
    413373        return head;
    414374}
     
    416376void BlockInternal() {
    417377        disable_interrupts();
    418         verify( !preemption.enabled );
    419         returnToKernel();
    420         verify( !preemption.enabled );
     378        verify( !preemption_enabled );
     379        returnToKernel();
     380        verify( !preemption_enabled );
    421381        enable_interrupts( __cfaabi_dbg_ctx );
    422382}
     
    427387        this_processor->finish.lock        = lock;
    428388
    429         verify( !preemption.enabled );
    430         returnToKernel();
    431         verify( !preemption.enabled );
     389        verify( !preemption_enabled );
     390        returnToKernel();
     391        verify( !preemption_enabled );
    432392
    433393        enable_interrupts( __cfaabi_dbg_ctx );
     
    439399        this_processor->finish.thrd        = thrd;
    440400
    441         verify( !preemption.enabled );
    442         returnToKernel();
    443         verify( !preemption.enabled );
     401        verify( !preemption_enabled );
     402        returnToKernel();
     403        verify( !preemption_enabled );
    444404
    445405        enable_interrupts( __cfaabi_dbg_ctx );
     
    453413        this_processor->finish.thrd        = thrd;
    454414
    455         verify( !preemption.enabled );
    456         returnToKernel();
    457         verify( !preemption.enabled );
     415        verify( !preemption_enabled );
     416        returnToKernel();
     417        verify( !preemption_enabled );
    458418
    459419        enable_interrupts( __cfaabi_dbg_ctx );
     
    466426        this_processor->finish.lock_count  = count;
    467427
    468         verify( !preemption.enabled );
    469         returnToKernel();
    470         verify( !preemption.enabled );
     428        verify( !preemption_enabled );
     429        returnToKernel();
     430        verify( !preemption_enabled );
    471431
    472432        enable_interrupts( __cfaabi_dbg_ctx );
     
    481441        this_processor->finish.thrd_count  = thrd_count;
    482442
    483         verify( !preemption.enabled );
    484         returnToKernel();
    485         verify( !preemption.enabled );
     443        verify( !preemption_enabled );
     444        returnToKernel();
     445        verify( !preemption_enabled );
    486446
    487447        enable_interrupts( __cfaabi_dbg_ctx );
     
    489449
    490450void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    491         verify( !preemption.enabled );
     451        verify( !preemption_enabled );
    492452        this_processor->finish.action_code = thrd ? Release_Schedule : Release;
    493453        this_processor->finish.lock        = lock;
     
    503463// Kernel boot procedures
    504464void kernel_startup(void) {
    505         verify( !preemption.enabled );
    506465        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    507466
     
    541500        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    542501        // mainThread is on the ready queue when this call is made.
    543         kernel_first_resume( this_processor );
     502        resume( *mainProcessor->runner );
    544503
    545504
     
    548507        __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n");
    549508
    550         verify( !preemption.enabled );
    551509        enable_interrupts( __cfaabi_dbg_ctx );
    552         verify( preemption.enabled );
    553510}
    554511
     
    556513        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    557514
    558         verify( preemption.enabled );
    559515        disable_interrupts();
    560         verify( !preemption.enabled );
    561516
    562517        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
  • src/libcfa/concurrency/kernel_private.h

    r7c782af rc71b256  
    7474extern thread_local processor *      volatile this_processor;
    7575
    76 // extern volatile thread_local bool preemption_in_progress;
    77 // extern volatile thread_local bool preemption_enabled;
    78 // extern volatile thread_local unsigned short disable_preempt_count;
    79 
    80 struct __cfa_kernel_preemption_data_t {
    81         bool enabled;
    82         bool in_progress;
    83         unsigned short disable_count;
    84 };
    85 
    86 extern volatile thread_local __cfa_kernel_preemption_data_t preemption;
     76extern volatile thread_local bool preemption_in_progress;
     77extern volatile thread_local bool preemption_enabled;
     78extern volatile thread_local unsigned short disable_preempt_count;
    8779
    8880//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor.c

    r7c782af rc71b256  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 16 14:49:53 2018
    13 // Update Count     : 5
     12// Last Modified On : Thu Feb  8 16:12:20 2018
     13// Update Count     : 4
    1414//
    1515
     
    427427                thread_desc * this_thrd = this_thread;
    428428                if ( this.monitor_count != this_thrd->monitors.size ) {
    429                         abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     429                        abort( "Signal on condition %p made with different number of monitor(s), expected %li got %li", &this, this.monitor_count, this_thrd->monitors.size );
    430430                }
    431431
  • src/libcfa/concurrency/preemption.c

    r7c782af rc71b256  
    149149        // Disable interrupts by incrementing the counter
    150150        void disable_interrupts() {
    151                 preemption.enabled = false;
    152                 __attribute__((unused)) unsigned short new_val = preemption.disable_count + 1;
    153                 preemption.disable_count = new_val;
     151                preemption_enabled = false;
     152                __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1;
     153                disable_preempt_count = new_val;
    154154                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    155155        }
     
    161161                thread_desc * thrd = this_thread;         // Cache the thread now since interrupts can start happening after the atomic add
    162162
    163                 unsigned short prev = preemption.disable_count;
    164                 preemption.disable_count -= 1;
     163                unsigned short prev = disable_preempt_count;
     164                disable_preempt_count -= 1;
    165165                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    166166
    167167                // Check if we need to prempt the thread because an interrupt was missed
    168168                if( prev == 1 ) {
    169                         preemption.enabled = true;
     169                        preemption_enabled = true;
    170170                        if( proc->pending_preemption ) {
    171171                                proc->pending_preemption = false;
     
    181181        // Don't execute any pending CtxSwitch even if counter reaches 0
    182182        void enable_interrupts_noPoll() {
    183                 unsigned short prev = preemption.disable_count;
    184                 preemption.disable_count -= 1;
     183                unsigned short prev = disable_preempt_count;
     184                disable_preempt_count -= 1;
    185185                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    186186                if( prev == 1 ) {
    187                         preemption.enabled = true;
     187                        preemption_enabled = true;
    188188                }
    189189        }
     
    235235// If false : preemption is unsafe and marked as pending
    236236static inline bool preemption_ready() {
    237         bool ready = preemption.enabled && !preemption.in_progress; // Check if preemption is safe
     237        bool ready = preemption_enabled && !preemption_in_progress; // Check if preemption is safe
    238238        this_processor->pending_preemption = !ready;                        // Adjust the pending flag accordingly
    239239        return ready;
     
    250250
    251251        // Start with preemption disabled until ready
    252         preemption.enabled = false;
    253         preemption.disable_count = 1;
     252        preemption_enabled = false;
     253        disable_preempt_count = 1;
    254254
    255255        // Initialize the event kernel
     
    290290// Used by thread to control when they want to receive preemption signals
    291291void ?{}( preemption_scope & this, processor * proc ) {
    292         (this.alarm){ proc, 0`cfa_s, 0`cfa_s };
     292        (this.alarm){ proc, zero_time, zero_time };
    293293        this.proc = proc;
    294294        this.proc->preemption_alarm = &this.alarm;
     
    300300        disable_interrupts();
    301301
    302         update_preemption( this.proc, 0`cfa_s );
     302        update_preemption( this.proc, zero_time );
    303303}
    304304
     
    330330        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
    331331
    332         preemption.in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
     332        preemption_in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
    333333        signal_unblock( SIGUSR1 );                          // We are about to CtxSwitch out of the signal handler, let other handlers in
    334         preemption.in_progress = false;                     // Clear the in progress flag
     334        preemption_in_progress = false;                     // Clear the in progress flag
    335335
    336336        // Preemption can occur here
  • src/libcfa/concurrency/thread.c

    r7c782af rc71b256  
    9090}
    9191
    92 extern "C" {
    93         void __finish_creation(void) {
    94                 coroutine_desc* thrd_c = this_coroutine;
    95                 ThreadCtxSwitch( thrd_c, thrd_c->last );
    96         }
    97 }
    98 
    9992void yield( void ) {
    100         verify( preemption.enabled );
    10193        BlockInternal( this_thread );
    102         verify( preemption.enabled );
    10394}
    10495
  • src/main.cc

    r7c782af rc71b256  
    282282                } // if
    283283
    284                 CodeTools::fillLocations( translationUnit );
    285 
    286284                OPTPRINT( "resolve" )
    287285                ResolvExpr::resolve( translationUnit );
     
    363361                        cerr << endl << "---End of AST, begin error message:---\n" << endl;
    364362                } // if
    365                 e.print();
     363                e.print( cerr );
    366364                if ( output != &cout ) {
    367365                        delete output;
  • src/tests/.expect/alloc.txt

    r7c782af rc71b256  
    22CFA malloc 0xdeadbeef
    33CFA alloc 0xdeadbeef
    4 CFA alloc, fill ffffffff
     4CFA alloc, fill 01010101
    55
    66C   array calloc, fill 0
     
    1010CFA array alloc, no fill
    11110xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    12 CFA array alloc, fill 0xff
    13 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
     12CFA array alloc, fill 0x1
     130x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101
    1414
    1515C   realloc
     
    25250xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    2626CFA resize array alloc, fill
    27 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
     270x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101
    2828CFA resize array alloc, fill
    29 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
     290x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101
    3030CFA resize array alloc, fill
    31 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
     310x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101
    3232
    3333C   memalign 42 42.5
     
    3737CFA aligned_alloc 42 42.5
    3838CFA align_alloc 42 42.5
    39 CFA align_alloc fill 0xffffffff -nan
     39CFA align_alloc fill 0x1010101 0x1.1010101010101p-1007
    4040
    4141CFA array align_alloc
    424242 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5, 42 42.5,
    4343CFA array align_alloc, fill
    44 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,
     440x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007,
    4545
    46 CFA memset 0xffffffff -nan
    47 CFA memcpy 0xffffffff -nan
     46CFA memset 0x1010101 0x1.1010101010101p-1007
     47CFA memcpy 0x1010101 0x1.1010101010101p-1007
    4848
    4949CFA array memset
    50 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,
     500x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007,
    5151CFA memcpy
    52 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,
     520x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007,
    5353
    5454CFA new initialize
  • src/tests/alloc.c

    r7c782af rc71b256  
    1010// Created On       : Wed Feb  3 07:56:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 16 15:42:31 2018
    13 // Update Count     : 330
     12// Last Modified On : Mon Jan 22 21:26:40 2018
     13// Update Count     : 326
    1414//
    1515
     
    2727int main( void ) {
    2828        size_t dim = 10;
    29         char fill = '\xff';
    3029        int * p;
     30        char fill = '\1';
    3131
    3232        // allocation, non-array types
     
    7979
    8080        p = alloc( 2 * dim, fill );                         // CFA array alloc, fill
    81         printf( "CFA array alloc, fill %#hhx\n", fill );
     81        printf( "CFA array alloc, fill %#x\n", fill );
    8282        for ( int i = 0; i < 2 * dim; i += 1 ) { printf( "%#x ", p[i] ); }
    8383        printf( "\n" );
  • src/tests/raii/.expect/dtor-early-exit-ERR2.txt

    r7c782af rc71b256  
    1 raii/dtor-early-exit.c:217:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
     1raii/dtor-early-exit.c:220:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
    22  with target: L2
    33  with original target: L2
Note: See TracChangeset for help on using the changeset viewer.