Changeset 7c782af


Ignore:
Timestamp:
Feb 16, 2018, 4:22:25 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
5964127
Parents:
c71b256 (diff), 62cd621 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

Files:
1 added
49 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

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

    rc71b256 r7c782af  
    44\usepackage{epic,eepic}
    55\usepackage{xspace,calc,comment}
    6 \usepackage{upquote}                                                                    % switch curled `'" to straight
    7 \usepackage{listings}                                                                   % format program code
     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
    810\usepackage{rotating}
    911\usepackage[usenames]{color}
    10 \usepackage{pslatex}                                    % reduce size of san serif font
     12\usepackage{pslatex}                                            % reduce size of san serif font
    1113\usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
    1214
    1315\setlength{\textheight}{9in}
    1416%\oddsidemargin 0.0in
    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
     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
    2123\righthyphenmin=4
    2224
     
    2426
    2527\newcommand{\CFAIcon}{\textsf{C}\raisebox{\depth}{\rotatebox{180}{\textsf{A}}}\xspace} % Cforall 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
     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
    2931\newcommand{\CC}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}\xspace} % C++ symbolic name
    3032\newcommand{\CCeleven}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
     
    5658\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    5759
    58 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     60\newlength{\gcolumnposn}                                        % temporary hack because lstlisting does not handle tabs correctly
    5961\newlength{\columnposn}
    6062\setlength{\gcolumnposn}{2.75in}
     
    7274
    7375% Latin abbreviation
    74 \newcommand{\abbrevFont}{\textit}       % set empty for no italics
     76\newcommand{\abbrevFont}{\textit}                       % set empty for no italics
    7577\newcommand{\EG}{\abbrevFont{e}.\abbrevFont{g}.}
    7678\newcommand*{\eg}{%
     
    103105
    104106\newenvironment{cquote}{%
    105         \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}%
     107        \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
    106108        \item\relax
    107109}{%
     
    187189
    188190
    189 \section{Introduction and Background}
     191\section{Introduction}
    190192
    191193The 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.
     
    193195The 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.
    194196The top 3 rankings over the past 30 years are:
    195 \lstDeleteShortInline@%
    196197\begin{center}
    197198\setlength{\tabcolsep}{10pt}
     199\lstDeleteShortInline@%
    198200\begin{tabular}{@{}rccccccc@{}}
    199201                & 2017  & 2012  & 2007  & 2002  & 1997  & 1992  & 1987          \\ \hline
     
    202204\CC             & 3             & 3             & 3             & 3             & 2             & 2             & 4                     \\
    203205\end{tabular}
     206\lstMakeShortInline@%
    204207\end{center}
    205 \lstMakeShortInline@%
    206208Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    207209In many cases, \CC is often used solely as a better C.
     
    224226The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance.
    225227
    226 
    227 \subsection{Polymorphic Functions}
     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
     234C 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.
     236Code 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.
     237As an example:
     238
     239\begin{cfa}
     240int max(int a, int b) { return a < b ? b : a; }  // (1)
     241double max(double a, double b) { return a < b ? b : a; }  // (2)
     242
     243int max = INT_MAX;     // (3)
     244double max = DBL_MAX;  // (4)
     245
     246max(7, -max);   $\C{// uses (1) and (3), by matching int from constant 7}$
     247max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$
     248
     249//max(max, -max);  $\C{// ERROR: ambiguous}$
     250int 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.
     254The 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@.
     255Ergonomic 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}}
    228258\label{sec:poly-fns}
    229259
    230 \CFA{}\hspace{1pt}'s polymorphism was originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
    231260The 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):
    232261\begin{lstlisting}
     
    257286Crucial to the design of a new programming language are the libraries to access thousands of external software features.
    258287Like \CC, \CFA inherits a massive compatible library-base, where other programming languages must rewrite or provide fragile inter-language communication with C.
    259 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted floating-point array:
     288A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:
    260289\begin{lstlisting}
    261290void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
     
    263292int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 :
    264293                                *(double *)t2 < *(double *)t1 ? 1 : 0; }
    265 double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ };
     294double key = 5.0, vals[10] = { /* 10 sorted float values */ };
    266295double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      $\C{// search sorted array}$
    267296\end{lstlisting}
     
    304333Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    305334
    306 Finally, \CFA allows variable overloading:
    307 \begin{lstlisting}
    308 short int MAX = ...;   int MAX = ...;  double MAX = ...;
    309 short int s = MAX;    int i = MAX;    double d = MAX;   $\C{// select correct MAX}$
    310 \end{lstlisting}
    311 Here, the single name @MAX@ replaces all the C type-specific names: @SHRT_MAX@, @INT_MAX@, @DBL_MAX@.
     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@.
    312343
    313344\subsection{Traits}
     
    505536In many languages, functions can return at most one value;
    506537however, many operations have multiple outcomes, some exceptional.
    507 Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and floating-point values, respectively.
     538Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively.
    508539\begin{lstlisting}
    509540typedef struct { int quo, rem; } div_t;         $\C{// from include stdlib.h}$
     
    936967
    937968\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.
    938971
    939972
     
    10441077The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
    10451078
     1079
    10461080\subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}}
    10471081
    1048 \CFA also fixes a number of ergonomic defecits in the @switch@ statements of standard C.
    1049 C 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:@.
    1050 For 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 
     1082There 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
     1084C 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}
     1091case 2, 10, 34, 42:
     1092\end{cfa}
     1093&
     1094\begin{cfa}
     1095case 2: case 10: case 34: case 42:
     1096\end{cfa}
     1097\end{tabular}
     1098\lstMakeShortInline@%
     1099\end{cquote}
     1100for 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}
     1106case 2~42:
     1107\end{cfa}
     1108&
     1109\begin{cfa}
     1110case 2: case 3: ... case 41: case 42:
     1111\end{cfa}
     1112\end{tabular}
     1113\lstMakeShortInline@%
     1114\end{cquote}
     1115and a combination:
     1116\begin{cfa}
     1117case -12~-4, -1~5, 14~21, 34~42:
     1118\end{cfa}
     1119
     1120C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83});
     1121\begin{cfa}
     1122switch ( 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
     1133C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
     1134\begin{cfa}
     1135switch ( 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
     1149C @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.
     1151While 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}
     1179switch ( 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}
     1201Collectively, these enhancements reduce programmer burden and increase readability and safety.
     1202
     1203\begin{comment}
    10521204Forgotten @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.
    10531205\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.
     
    10701222}
    10711223\end{cfa}
     1224\end{comment}
     1225
    10721226
    10731227\subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}}
     
    12061360\end{cfa}
    12071361
    1208 
    1209 \subsection{Exception Handling ???}
    1210 
     1362% \subsection{Exception Handling ???}
    12111363
    12121364\section{Declarations}
     
    12551407\lstDeleteShortInline@%
    12561408\lstset{moredelim=**[is][\color{blue}]{+}{+}}
    1257 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1258 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1409\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1410\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    12591411\begin{cfa}
    12601412+[5] *+ `int` x1;
    12611413+* [5]+ `int` x2;
    1262 +[* [5] int]+ f`( int p )`;
     1414`[* [5] int]` f+( int p )+;
    12631415\end{cfa}
    12641416&
     
    12661418`int` +*+ x1 +[5]+;
    12671419`int` +(*+x2+)[5]+;
    1268 +int (*+f`( int p )`+)[5]+;
     1420`int (*`f+( int p )+`)[5]`;
    12691421\end{cfa}
    12701422\end{tabular}
     
    12771429\begin{cquote}
    12781430\lstDeleteShortInline@%
    1279 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1280 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1431\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1432\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    12811433\begin{cfa}
    12821434`*` int x, y;
     
    12921444\begin{cquote}
    12931445\lstDeleteShortInline@%
    1294 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1295 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1446\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1447\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    12961448\begin{cfa}
    12971449`*` int x;
     
    13101462\begin{cquote}
    13111463\lstDeleteShortInline@%
    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}} \\
     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}}      \\
    13141466\begin{cfa}
    13151467[ 5 ] int z;
     
    13511503\begin{cquote}
    13521504\lstDeleteShortInline@%
    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}} \\
     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}}      \\
    13551507\begin{cfa}
    13561508const * const int x;
     
    13741526\begin{cquote}
    13751527\lstDeleteShortInline@%
    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}} \\
     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}}      \\
    13781530\begin{cfa}
    13791531extern [ 5 ] int x;
     
    13971549\begin{cquote}
    13981550\lstDeleteShortInline@%
    1399 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1400 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1551\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1552\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    14011553\begin{cfa}
    14021554y = (* int)x;
     
    14151567Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    14161568Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
     1569
     1570The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;
     1571as 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}
     1578This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     1579Like 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}
     1589double 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
     1596Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
     1597\begin{cfa}
     1598extern [ int ] f ( int );
     1599static [ int ] g ( int );
     1600\end{cfa}
     1601
     1602The 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}
     1609While parameter names are optional, \emph{a routine name cannot be specified};
     1610for example, the following is incorrect:
     1611\begin{cfa}
     1612* [ int x ] f () fp;                                    $\C{// routine name "f" is not allowed}$
     1613\end{cfa}
    14171614
    14181615
     
    15931790In 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.
    15941791
     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}
     1803struct 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
     1813int 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}
     1822enum C { R, G, B };
     1823union U { int i, j; };
     1824struct T {
     1825        enum C c;
     1826        short int i, j;
     1827};
     1828struct S {
     1829        struct T t;
     1830} s;
     1831       
     1832
     1833
     1834
     1835
     1836
     1837
     1838\end{cfa}
     1839&
     1840\begin{cfa}
     1841struct 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
     1851int 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}
     1863In the left example in C, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
     1864In 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
    15951867\subsection{Default Parameters}
    15961868
     
    15981870\section{Literals}
    15991871
    1600 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 floating-point types are very similar, differing from each other only in suffix.
     1872C 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.
    16011873In 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.
    16021874
     
    16221894struct Weight { double stones; };
    16231895
    1624 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$
     1896void ?{}( Weight & w ) { w.stones = 0; }        $\C{// operations}$
    16251897void ?{}( Weight & w, double w ) { w.stones = w; }
    16261898Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; }
     
    16311903
    16321904int main() {
    1633         Weight w, hw = { 14 };                  $\C{// 14 stone}$
     1905        Weight w, hw = { 14 };                                  $\C{// 14 stone}$
    16341906        w = 11@`st@ + 1@`lb@;
    16351907        w = 70.3@`kg@;
    16361908        w = 155@`lb@;
    1637         w = 0x_9b_u@`lb@;                               $\C{// hexadecimal unsigned weight (155)}$
    1638         w = 0_233@`lb@;                                 $\C{// octal weight (155)}$
     1909        w = 0x_9b_u@`lb@;                                               $\C{// hexadecimal unsigned weight (155)}$
     1910        w = 0_233@`lb@;                                                 $\C{// octal weight (155)}$
    16391911        w = 5@`st@ + 8@`kg@ + 25@`lb@ + hw;
    16401912}
    16411913\end{cfa}
    16421914}%
     1915
     1916
     1917\section{Libraries}
     1918\label{sec:libraries}
     1919
     1920As 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.
     1922In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime.
     1923The following sections give a glimpse of the interface reduction to many C libraries.
     1924In 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
     1929C 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}
     1936const short int `MIN` = -32768;
     1937const int `MIN` = -2147483648;
     1938const long int `MIN` = -9223372036854775808L;
     1939\end{cfa}
     1940&
     1941\begin{cfa}
     1942short int si = `MIN`;
     1943int i = `MIN`;
     1944long int li = `MIN`;
     1945\end{cfa}
     1946\end{tabular}
     1947\lstMakeShortInline@%
     1948\end{cquote}
     1949The 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}
     1955MIN
     1956MAX
     1957M_PI
     1958M_E
     1959\end{cfa}
     1960&
     1961\begin{cfa}
     1962SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN,
     1963SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX,
     1964M_PI, M_PIl, M_CPI, M_CPIl,
     1965M_E, M_El, M_CE, M_CEl
     1966\end{cfa}
     1967\end{tabular}
     1968\lstMakeShortInline@%
     1969\end{cquote}
     1970
     1971
     1972\subsection{Math}
     1973
     1974C 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}
     1981float `log`( float x );
     1982double `log`( double );
     1983double _Complex `log`( double _Complex x );
     1984\end{cfa}
     1985&
     1986\begin{cfa}
     1987float f = `log`( 3.5 );
     1988double d = `log`( 3.5 );
     1989double _Complex dc = `log`( 3.5+0.5I );
     1990\end{cfa}
     1991\end{tabular}
     1992\lstMakeShortInline@%
     1993\end{cquote}
     1994The 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}
     2000log
     2001sqrt
     2002sin
     2003\end{cfa}
     2004&
     2005\begin{cfa}
     2006logf, log, logl, clogf, clog, clogl
     2007sqrtf, sqrt, sqrtl, csqrtf, csqrt, csqrtl
     2008sinf, sin, sinl, csinf, csin, csinl
     2009\end{cfa}
     2010\end{tabular}
     2011\lstMakeShortInline@%
     2012\end{cquote}
     2013While \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).
     2014For example, it is not possible to overload @atan@ for both one and two arguments;
     2015instead the names @atan@ and @atan2@ are required.
     2016The 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
     2021C 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}
     2028unsigned int `abs`( int );
     2029double `abs`( double );
     2030double abs( double _Complex );
     2031\end{cfa}
     2032&
     2033\begin{cfa}
     2034unsigned int i = `abs`( -1 );
     2035double d = `abs`( -1.5 );
     2036double d = `abs`( -1.5+0.5I );
     2037\end{cfa}
     2038\end{tabular}
     2039\lstMakeShortInline@%
     2040\end{cquote}
     2041The 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}
     2047abs
     2048strto
     2049random
     2050\end{cfa}
     2051&
     2052\begin{cfa}
     2053abs, labs, llabs, fabsf, fabs, fabsl, cabsf, cabs, cabsl
     2054strtol, strtoul, strtoll, strtoull, strtof, strtod, strtold
     2055srand48, mrand48, lrand48, drand48
     2056\end{cfa}
     2057\end{tabular}
     2058\lstMakeShortInline@%
     2059\end{cquote}
     2060In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.
     2061
     2062The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
     2063C/\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]
     2066after allocation the storage is filled with a specified character.
     2067\item[resize]
     2068an existing allocation is decreased or increased in size.
     2069In 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.
     2070For an increase in storage size, new storage after the copied data may be filled.
     2071\item[alignment]
     2072an allocation starts on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
     2073\item[array]
     2074the allocation size is scaled to the specified number of array elements.
     2075An array may be filled, resized, or aligned.
     2076\end{description}
     2077Table~\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.
     2080The 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]
     2083size_t  dim = 10;                                                       $\C{// array dimension}$
     2084char fill = '\xff';                                                     $\C{// initialization fill value}$
     2085int * 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}
     2091ip = alloc();
     2092ip = alloc( fill );
     2093ip = alloc( dim );
     2094ip = alloc( dim, fill );
     2095ip = alloc( ip, 2 * dim );
     2096ip = alloc( ip, 4 * dim, fill );
     2097
     2098ip = align_alloc( 16 );
     2099ip = align_alloc( 16, fill );
     2100ip = align_alloc( 16, dim );
     2101ip = align_alloc( 16, dim, fill );
     2102\end{cfa}
     2103&
     2104\begin{cfa}
     2105ip = (int *)malloc( sizeof( int ) );
     2106ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
     2107ip = (int *)malloc( dim * sizeof( int ) );
     2108ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
     2109ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
     2110ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) );
     2111
     2112ip = memalign( 16, sizeof( int ) );
     2113ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
     2114ip = memalign( 16, dim * sizeof( int ) );
     2115ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
     2116\end{cfa}
     2117\end{tabular}
     2118\lstMakeShortInline@%
     2119\end{cquote}
     2120Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
     2121Hence, 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}
     2123struct S { int i, j; };
     2124void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; }
     2125S * s = new( 2, 3 );                                            $\C{// allocate storage and run constructor}$
     2126S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
     2127\end{cfa}
     2128Note, \CC can only initialization array elements via the default constructor.
     2129
     2130Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
     2131When 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
     2140C               & ~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
     2146C11             & ~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
     2161The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user defined types in a consistent way.
     2162The approach combines ideas from \CC and Python.
     2163The \CFA header file for the I/O library is @fstream@.
     2164
     2165The 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}
     2171int x = 1, y = 2, z = 3;
     2172sout | x `|` y `|` z | endl;
     2173\end{cfa}
     2174&
     2175\begin{cfa}
     2176
     2177cout << x `<< " "` << y `<< " "` << z << endl;
     2178\end{cfa}
     2179\\
     2180\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     21811` `2` `3
     2182\end{cfa}
     2183&
     2184\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     21851 2 3
     2186\end{cfa}
     2187\end{tabular}
     2188\lstMakeShortInline@%
     2189\end{cquote}
     2190The \CFA form has half the characters of the \CC form, and is similar to Python I/O with respect to implicit separators.
     2191Similar 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 ] ];
     2194sout | t1 | t2 | endl;                                  $\C{// print tuples}$
     2195\end{cfa}
     2196\begin{cfa}[showspaces=true,aboveskip=0pt]
     21971`, `2`, `3 4`, `5`, `6
     2198\end{cfa}
     2199Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
     2200Therefore, fewer output expressions require parenthesis.
     2201\begin{cquote}
     2202\lstDeleteShortInline@%
     2203\begin{tabular}{@{}ll@{}}
     2204\textbf{\CFA:}
     2205&
     2206\begin{cfa}
     2207sout | 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}
     2213cout << 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]
     22193 3 12 0 3 1 2
     2220\end{cfa}
     2221\end{tabular}
     2222\lstMakeShortInline@%
     2223\end{cquote}
     2224There 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
     2226The implicit separator character (space/blank) is a separator not a terminator.
     2227The rules for implicitly adding the separator are:
     2228\begin{itemize}[itemsep=2pt,parsep=0pt]
     2229\item
     2230A separator does not appear at the start or end of a line.
     2231\item
     2232A separator does not appear before or after a character literal or variable.
     2233\item
     2234A 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
     2236A separator does not appear before a C string starting with the characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$@
     2237\item
     2238A seperator does not appear after a C string ending with the characters: \lstinline[basicstyle=\tt]@,.;!?)]}%@
     2239\item
     2240{\lstset{language=CFA,deletedelim=**[is][]{`}{`}}
     2241A 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
     2244There 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.
     2252The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.
     2253The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@.
     2254The 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>
     2261int 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>
     2275int 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
    16432290
    16442291\section{Evaluation}
     
    17042351
    17052352\begin{table}
     2353\centering
    17062354\caption{Properties of benchmark code}
    17072355\label{tab:eval}
  • doc/user/user.tex

    rc71b256 r7c782af  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Jan 31 22:29:25 2018
    14 %% Update Count     : 3147
     13%% Last Modified On : Tue Feb 13 08:31:21 2018
     14%% Update Count     : 3161
    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{quote2}
     163\begin{cquote}
    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{quote2}
     193\end{cquote}
    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-point array:
     276A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating 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-point values */ };
     284double key = 5.0, vals[10] = { /* 10 sorted floating 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 point constant}§
    447 10®_®e®_®+1®_®00;                                               §\C{// floating point constant}§
    448 0x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating point
    449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating point long constant}§
     4463.141®_®592®_®654;                                              §\C{// floating constant}§
     44710®_®e®_®+1®_®00;                                               §\C{// floating constant}§
     4480x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating
     4490x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating 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
     507C, \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$.
     509The 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
     511As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
     512Unsigned 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).
     513Signed 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$.
     514Hence, 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.
     515Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
     516\begin{cfa}
     517sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
     518256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     519\end{cfa}
     520Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
     521The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
     522For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
     523for returning a floating value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents.
    503524
    504525
     
    628649\end{cfa}
    629650The ability to fall-through to the next clause \emph{is} a useful form of control flow, specifically when a sequence of case actions compound:
    630 \begin{quote2}
     651\begin{cquote}
    631652\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    632653\begin{cfa}
     
    656677\end{cfa}
    657678\end{tabular}
    658 \end{quote2}
     679\end{cquote}
    659680In this example, case 2 is always done if case 3 is done.
    660681This 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.
     
    730751        ®int y = 1;®                            §\C{// unreachable initialization}§
    731752        ®x = 7;®                                        §\C{// unreachable code without label/branch}§
    732   case 3: ...
     753  case 0: ...
    733754        ...
    734755        ®int z = 0;®                            §\C{// unreachable initialization, cannot appear after case}§
    735756        z = 2;
    736   case 3:
     757  case 1:
    737758        ®x = z;®                                        §\C{// without fall through, z is uninitialized}§
    738759}
     
    819840Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
    820841Therefore, the ©case© clause is extended with a list of values, as in:
    821 \begin{quote2}
     842\begin{cquote}
    822843\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    823844\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    849870\end{cfa}
    850871\end{tabular}
    851 \end{quote2}
     872\end{cquote}
    852873In addition, two forms of subranges are allowed to specify case values: a new \CFA form and an existing GNU C form.\footnote{
    853874The GNU C form \emph{requires} spaces around the ellipse.}
    854 \begin{quote2}
     875\begin{cquote}
    855876\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    856877\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{GNU C}}     \\
     
    882903\end{cfa}
    883904\end{tabular}
    884 \end{quote2}
     905\end{cquote}
    885906Lists of subranges are also allowed.
    886907\begin{cfa}
     
    902923}
    903924\end{C++}
    904 Since CFA is non-object-oriented, the equivalent object-oriented program looks like:
     925Since \CFA is non-object-oriented, the equivalent object-oriented program looks like:
    905926\begin{cfa}
    906927struct S { int i, j; };
    907 int mem( S &®this® ) {                  §\C{// explicit "this" parameter}§
     928int mem( S & ®this® ) {                 §\C{// explicit "this" parameter}§
    908929        ®this.®i = 1;                           §\C{// "this" is not elided}§
    909930        ®this.®j = 2;
    910931}
    911932\end{cfa}
    912 but it is cumbersome having to write "©this.©" many times in a member.
     933but it is cumbersome having to write ``©this.©'' many times in a member.
    913934
    914935\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.
    915936\begin{cfa}
    916 int mem( S &this ) ®with this® { §\C{// with clause}§
    917         i = 1;                                          §\C{\color{red}// this->i}§
    918         j = 2;                                          §\C{\color{red}// this->j}§
     937int mem( S & this ) ®with this® { §\C{// with clause}§
     938        i = 1;                                          §\C{\color{red}// this.i}§
     939        j = 2;                                          §\C{\color{red}// this.j}§
    919940}
    920941\end{cfa}
     
    922943\begin{cfa}
    923944struct T { double m, n; };
    924 int mem2( S &this1, T &this2 ) ®with this1, this2® {
     945int mem2( S & this1, T & this2 ) ®with this1, this2® {
    925946        i = 1; j = 2;
    926947        m = 1.0; n = 2.0;
     
    933954        struct S1 { ... } s1;
    934955        struct S2 { ... } s2;
    935         ®with s1® {                     // with statement
     956        ®with s1® {                                     §\C{// with statement}§
    936957                // access fields of s1 without qualification
    937                 ®with s2® {  // nesting
     958                ®with s2® {                             §\C{// nesting}§
    938959                        // access fields of s1 and s2 without qualification
    939960                }
     
    10451066
    10461067
    1047 \section{Declarations}
    1048 \label{s:Declarations}
     1068\section{Alternative Declarations}
     1069\label{s:AlternativeDeclarations}
    10491070
    10501071C declaration syntax is notoriously confusing and error prone.
    10511072For example, many C programmers are confused by a declaration as simple as:
    1052 \begin{quote2}
     1073\begin{cquote}
    10531074\begin{tabular}{@{}ll@{}}
    10541075\begin{cfa}
     
    10581079\raisebox{-0.75\totalheight}{\input{Cdecl}}
    10591080\end{tabular}
    1060 \end{quote2}
     1081\end{cquote}
    10611082Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers?
    1062 The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs.
     1083If there is any doubt, it implies \Index{productivity} and \Index{safety} issues even for basic programs.
    10631084Another 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.
    10641085For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    10651086\begin{cfa}
    1066 int ®(*®f®())[®5®]® {...};                              §\C{definition}§
    1067  ... ®(*®f®())[®3®]® += 1;                              §\C{usage}§
     1087int ®(*®f®())[®5®]® {...};                              §\C{// definition}§
     1088 ... ®(*®f®())[®3®]® += 1;                              §\C{// usage}§
    10681089\end{cfa}
    10691090Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
     
    10741095In the following example, \R{red} is the base type and \B{blue} is qualifiers.
    10751096The \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.
    1076 \begin{quote2}
     1097\begin{cquote}
    10771098\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    10781099\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    10891110\end{cfa}
    10901111\end{tabular}
    1091 \end{quote2}
     1112\end{cquote}
    10921113The only exception is \Index{bit field} specification, which always appear to the right of the base type.
    10931114% 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.
    10941115However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    10951116For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows:
    1096 \begin{quote2}
     1117\begin{cquote}
    10971118\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    10981119\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    11051126\end{cfa}
    11061127\end{tabular}
    1107 \end{quote2}
     1128\end{cquote}
    11081129The downside of this semantics is the need to separate regular and \Index{pointer} declarations:
    1109 \begin{quote2}
     1130\begin{cquote}
    11101131\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    11111132\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     
    11201141\end{cfa}
    11211142\end{tabular}
    1122 \end{quote2}
     1143\end{cquote}
    11231144which is \Index{prescribing} a safety benefit.
    11241145Other examples are:
    1125 \begin{quote2}
     1146\begin{cquote}
    11261147\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    11271148\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    11591180\end{cfa}
    11601181\end{tabular}
    1161 \end{quote2}
     1182\end{cquote}
    11621183
    11631184All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
    1164 \begin{quote2}
     1185\begin{cquote}
    11651186\begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    11661187\multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
     
    11801201\end{cfa}
    11811202\end{tabular}
    1182 \end{quote2}
     1203\end{cquote}
    11831204All 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}
    11841205The 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:
    1185 \begin{quote2}
     1206\begin{cquote}
    11861207\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    11871208\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     
    12011222\end{cfa}
    12021223\end{tabular}
    1203 \end{quote2}
     1224\end{cquote}
    12041225
    12051226The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©:
    1206 \begin{quote2}
     1227\begin{cquote}
    12071228\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    12081229\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    12091230\begin{cfa}
    1210 y = (®* int®)x;
    1211 i = sizeof(®[ 5 ] * int®);
     1231y = (* int)x;
     1232i = sizeof([ 5 ] * int);
    12121233\end{cfa}
    12131234&
    12141235\begin{cfa}
    1215 y = (®int *®)x;
    1216 i = sizeof(®int * [ 5 ]®);
     1236y = (int *)x;
     1237i = sizeof(int * [ 5 ]);
    12171238\end{cfa}
    12181239\end{tabular}
    1219 \end{quote2}
     1240\end{cquote}
    12201241
    12211242Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    12221243Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1223 Clearly, 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 
    1228 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.
    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$.
    1230 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)©.
    1231 
    1232 As for \Index{division}, there are exponentiation operators for integral and floating-point types, including the builtin \Index{complex} types.
    1233 Unsigned 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).
    1234 Signed 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$.
    1235 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-point result.
    1236 Floating-point exponentiation\index{exponentiation!floating point} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
    1237 \begin{cfa}
    1238 sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
    1239 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
    1240 \end{cfa}
    1241 Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
    1242 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
    1243 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
    1244 for 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.
     1244Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
    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{quote2}
     1262\begin{cquote}
    12631263\begin{tabular}{@{}ll@{\hspace{2em}}l@{}}
    12641264\begin{cfa}
     
    12781278\end{cfa}
    12791279\end{tabular}
    1280 \end{quote2}
     1280\end{cquote}
    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{quote2}
     1286\begin{cquote}
    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{quote2}
     1304\end{cquote}
    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{quote2}
     1311\begin{cquote}
    13121312\begin{tabular}{@{}l@{\hspace{2em}}l@{}}
    13131313\begin{cfa}
     
    13211321\raisebox{-0.5\totalheight}{\input{pointer2.pstex_t}}
    13221322\end{tabular}
    1323 \end{quote2}
     1323\end{cquote}
    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:Declarations}) attempt to address this issue:
    1429 \begin{quote2}
     1428\CFA-style declarations (see \VRef{s:AlternativeDeclarations}) attempt to address this issue:
     1429\begin{cquote}
    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{quote2}
     1442\end{cquote}
    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:Declarations}), \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:AlternativeDeclarations}), \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{quote2}
     2074\begin{cquote}
    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{quote2}
     2089\end{cquote}
    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-point value.
     2274For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating 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{quote2}
     2997\begin{cquote}
    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{quote2}
     3018\end{cquote}
    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{quote2}
     3030\begin{cquote}
    30313031\begin{tabular}{@{}ll@{}}
    30323032\textbf{\CFA:}
     
    30473047\end{cfa}
    30483048\end{tabular}
    3049 \end{quote2}
     3049\end{cquote}
    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{quote2}
     3636\begin{cquote}
    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{quote2}
     3660\end{cquote}
    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{quote2}
     5723\begin{cquote}
    57245724\input{../refrat/keywords}
    5725 \end{quote2}
     5725\end{cquote}
    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{quote2}
     5732\begin{cquote}
    57335733\begin{tabular}{@{}llllll|l@{}}
    57345734\multicolumn{6}{c|}{C11} & \multicolumn{1}{c}{\CFA}             \\
     
    57905790\end{tabular}
    57915791\end{tabular}
    5792 \end{quote2}
     5792\end{cquote}
    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{quote2}
     6533\begin{cquote}
    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{quote2}
     6565\end{cquote}
    65666566
    65676567\begin{figure}
  • src/CodeGen/FixMain.cc

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

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

    rc71b256 r7c782af  
    7777                        maybeAccept_impl( *i, visitor );
    7878                } catch( SemanticError &e ) {
    79                         e.set_location( (*i)->location );
    8079                        errors.append( e );
    8180                }
     
    104103                        maybeMutate_impl( *i, mutator );
    105104                } catch( SemanticError &e ) {
    106                         e.set_location( (*i)->location );
    107105                        errors.append( e );
    108106                }
     
    134132                        }
    135133                } catch( SemanticError &e ) {
    136                         e.set_location( (*i)->location );
    137134                        errors.append( e );
    138135                }
     
    163160                        } // if
    164161                } catch( SemanticError &e ) {
    165                         e.set_location( (*i)->location );
    166162                        errors.append( e );
    167163                } // try
     
    200196
    201197                } catch ( SemanticError &e ) {
    202                         e.set_location( (*i)->location );
    203198                        errors.append( e );
    204199                }
  • src/Common/SemanticError.cc

    rc71b256 r7c782af  
    2323#include "SemanticError.h"
    2424
    25 SemanticError::SemanticError() {
    26 }
    27 
    28 SemanticError::SemanticError( std::string error ) {
    29         append( error );
     25SemanticError::SemanticError( CodeLocation location, std::string error ) {
     26        append( location, error );
    3027}
    3128
     
    3431}
    3532
    36 void SemanticError::append( const std::string & msg ) {
    37         errors.emplace_back( error_str() + msg );
     33void SemanticError::append( CodeLocation location, const std::string & msg ) {
     34        errors.emplace_back( location, msg );
    3835}
    3936
     
    4239}
    4340
    44 void SemanticError::print( std::ostream &os ) {
     41void SemanticError::print() {
    4542        using std::to_string;
    4643        for( auto err : errors ) {
    47                 os << err.location << err.description << std::endl;
     44                std::cerr << bold() << err.location << error_str() << reset_font() << err.description << std::endl;
    4845        }
    4946}
    5047
    51 void SemanticError::set_location( const CodeLocation& location ) {
    52         errors.begin()->maybeSet( location );
     48SemanticWarning::SemanticWarning( CodeLocation location, std::string msg ) {
     49        std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl;
    5350}
    5451
  • src/Common/SemanticError.h

    rc71b256 r7c782af  
    2424#include "CodeLocation.h"                                                               // for CodeLocation, toString
    2525
     26//-----------------------------------------------------------------------------
     27// Errors
    2628struct error {
     29        CodeLocation location;
    2730        std::string description;
    28         CodeLocation location;
    2931
    3032        error() = default;
    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         }
     33        error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {}
    3834};
    3935
    4036class SemanticError : public std::exception {
    4137  public:
    42         SemanticError();
    43         SemanticError( std::string error );
    44         template< typename T > SemanticError( const std::string & error, const T * obj );
     38        SemanticError() = default;
     39        SemanticError( CodeLocation location, std::string error );
    4540        ~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);
    4645
    4746        static inline const std::string & error_str() {
     
    5150
    5251        void append( SemanticError & other );
    53         void append( const std::string & );
     52        void append( CodeLocation location, const std::string & );
    5453        bool isEmpty() const;
    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)
     54        void print();
    6055  private:
    6156        std::list< error > errors;
     
    6358
    6459template< typename T >
    65 SemanticError::SemanticError( const std::string & error, const T * obj ) {
    66         append( toString( error, obj ) );
     60SemanticError::SemanticError( const T * obj, const std::string & error )
     61        : SemanticError( obj->location, toString( error, obj ) )
     62{}
     63
     64template< typename T >
     65SemanticError::SemanticError( CodeLocation location, const T * obj, const std::string & error )
     66        : SemanticError( location, toString( error, obj ) )
     67{}
     68
     69//-----------------------------------------------------------------------------
     70// Warnings
     71class 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
     88template< typename T >
     89SemanticWarning::SemanticWarning( const T * obj, const std::string & error )
     90        : SemanticWarning( obj->location, toString( error, obj ) )
     91{}
     92
     93template< typename T >
     94SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error )
     95        : SemanticWarning( location, toString( error, obj ) )
     96{}
     97
     98//-----------------------------------------------------------------------------
     99// Helpers
     100static inline const std::string & bold_ttycode() {
     101        static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
     102        return str;
     103}
     104
     105static inline const std::string & reset_font_ttycode() {
     106        static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : "";
     107        return str;
     108}
     109
     110static inline std::string make_bold( const std::string & str ) {
     111        return bold_ttycode() + str + reset_font_ttycode();
     112}
     113
     114struct bold {};
     115static inline std::ostream & operator<<(std::ostream & os, bold) {
     116        os << bold_ttycode();
     117        return os;
     118}
     119
     120struct reset_font {};
     121static inline std::ostream & operator<<(std::ostream & os, reset_font) {
     122        os << reset_font_ttycode();
     123        return os;
    67124}
    68125
  • src/Concurrency/Keywords.cc

    rc71b256 r7c782af  
    276276                        handle( decl );
    277277                }
    278 
    279278        }
    280279
     
    282281                if( ! decl->body ) return;
    283282
    284                 if( !type_decl ) throw SemanticError( context_error, decl );
     283                if( !type_decl ) throw SemanticError( decl, context_error );
    285284
    286285                FunctionDecl * func = forwardDeclare( decl );
     
    419418                if( mutexArgs.empty() ) return;
    420419
    421                 if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
     420                if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters" );
    422421
    423422                bool isDtor = CodeGen::isDestructor( decl->name );
    424423
    425                 if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
     424                if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument" );
    426425
    427426                for(auto arg : mutexArgs) {
     
    432431                if( ! body ) return;
    433432
    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 );
     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>" );
    437436
    438437                if( isDtor ) {
     
    480479                //Makes sure it's not a copy
    481480                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
    482                 if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg );
     481                if( ! rty ) throw SemanticError( arg, "Mutex argument must be of reference type " );
    483482
    484483                //Make sure the we are pointing directly to a type
    485484                Type* base = rty->get_base();
    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 );
     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 " );
    488487
    489488                //Make sure that typed isn't mutex
    490                 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
     489                if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument " );
    491490        }
    492491
     
    626625                if( type && type->get_baseStruct()->is_thread() ) {
    627626                        if( !thread_decl || !thread_ctor_seen ) {
    628                                 throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
     627                                throw SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
    629628                        }
    630629
  • src/Concurrency/Waitfor.cc

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

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

    rc71b256 r7c782af  
    9292                        } else if ( labelTable[ l ]->defined() ) {
    9393                                // defined twice, error
    94                                 throw SemanticError( "Duplicate definition of label: " + l.get_name() );
     94                                throw SemanticError( l.get_statement()->location, "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( "Use of undefined label: " + i->first.get_name() );
     123                                throw SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
    124124                        }
    125125                        (*ret)[ i->first ] = i->second->get_definition();
  • src/ControlStruct/MLEMutator.cc

    rc71b256 r7c782af  
    115115                                        } else {
    116116                                                // break target is outmost control structure
    117                                                 if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
     117                                                if ( enclosingControlStructures.empty() ) throw SemanticError( branchStmt->location, "'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( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
     126                                        throw SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
    127127                                } // if
    128128                                break;
  • src/GenPoly/Box.cc

    rc71b256 r7c782af  
    229229                                } // if
    230230                        } catch( SemanticError &e ) {
    231                                 e.set_location( (*i)->location );
    232231                                errors.append( e );
    233232                        } // try
     
    576575                                                }
    577576                                        } else {
    578                                                 throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
     577                                                throw SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
    579578                                        }
    580579                                }
     
    598597                                        } else {
    599598                                                // xxx - should this be an assertion?
    600                                                 throw SemanticError( toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ), appExpr );
     599                                                throw SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
    601600                                        } // if
    602601                                } // if
  • src/InitTweak/FixInit.cc

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

    rc71b256 r7c782af  
    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( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
     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" );
    320320                        // constructed objects should not have initializers nested too deeply
    321                         if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
     321                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( objDecl, "Managed object's initializer is too deep " );
    322322
    323323                        objDecl->set_init( genCtorInit( objDecl ) );
  • src/InitTweak/InitTweak.cc

    rc71b256 r7c782af  
    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( "unbalanced list initializers" );
     227                                        throw SemanticError( init->location, "unbalanced list initializers" );
    228228                                }
    229229
  • src/Parser/DeclarationNode.cc

    rc71b256 r7c782af  
    581581                                        dst->basictype = src->basictype;
    582582                                } else if ( src->basictype != DeclarationNode::NoBasicType )
    583                                         throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ", src );
     583                                        throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " );
    584584
    585585                                if ( dst->complextype == DeclarationNode::NoComplexType ) {
    586586                                        dst->complextype = src->complextype;
    587587                                } else if ( src->complextype != DeclarationNode::NoComplexType )
    588                                         throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ", src );
     588                                        throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " );
    589589
    590590                                if ( dst->signedness == DeclarationNode::NoSignedness ) {
    591591                                        dst->signedness = src->signedness;
    592592                                } else if ( src->signedness != DeclarationNode::NoSignedness )
    593                                         throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ", src );
     593                                        throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
    594594
    595595                                if ( dst->length == DeclarationNode::NoLength ) {
     
    598598                                        dst->length = DeclarationNode::LongLong;
    599599                                } else if ( src->length != DeclarationNode::NoLength )
    600                                         throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ", src );
     600                                        throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
    601601                        } // if
    602602                        break;
     
    966966                        } // if
    967967                } catch( SemanticError &e ) {
    968                         e.set_location( cur->location );
    969968                        errors.append( e );
    970969                } // try
     
    10011000                        } // if
    10021001                } catch( SemanticError &e ) {
    1003                         e.set_location( cur->location );
    10041002                        errors.append( e );
    10051003                } // try
     
    10201018                        * out++ = cur->buildType();
    10211019                } catch( SemanticError &e ) {
    1022                         e.set_location( cur->location );
    10231020                        errors.append( e );
    10241021                } // try
     
    10321029
    10331030Declaration * DeclarationNode::build() const {
    1034         if ( ! error.empty() ) throw SemanticError( error + " in declaration of ", this );
     1031        if ( ! error.empty() ) throw SemanticError( this, error + " in declaration of " );
    10351032
    10361033        if ( asmStmt ) {
     
    10551052                //    inline _Noreturn int i;                   // disallowed
    10561053                if ( type->kind != TypeData::Function && funcSpecs.any() ) {
    1057                         throw SemanticError( "invalid function specifier for ", this );
     1054                        throw SemanticError( this, "invalid function specifier for " );
    10581055                } // if
    10591056                return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
     
    10651062        //    inlne _Noreturn enum   E { ... };         // disallowed
    10661063        if ( funcSpecs.any() ) {
    1067                 throw SemanticError( "invalid function specifier for ", this );
     1064                throw SemanticError( this, "invalid function specifier for " );
    10681065        } // if
    10691066        assertf( name, "ObjectDecl must a have name\n" );
  • src/Parser/ExpressionNode.cc

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

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

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

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

    rc71b256 r7c782af  
    3131using namespace std;
    3232
    33 TypeData::TypeData( Kind k ) : kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
     33TypeData::TypeData( Kind k ) : location( yylloc ), 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( string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
     523        throw SemanticError( yylloc, 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, scs, typebuild( td->base ), linkage );
     802                ret = new TypedefDecl( name, td->location, 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( string( "duplicate declaration name " ) + *param->name );
     925                                if ( param->type ) throw SemanticError( param->location, 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( string( "duplicate parameter name " ) + *param->name );
     928                                if ( ! decl->type ) throw SemanticError( param->location, 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( string( "missing name in parameter list " ) + *decl->name );
     935                if ( decl->type ) throw SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
    936936        } // for
    937937
  • src/Parser/TypeData.h

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

    rc71b256 r7c782af  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec 21 11:32:56 2017
    13 // Update Count     : 2996
     12// Last Modified On : Thu Feb 15 17:12:31 2018
     13// Update Count     : 3006
    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("Qualified names are currently unimplemented."); $$ = nullptr; }                                                          // FIX ME
     484                { throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
    485485        | type_name '.' '[' push field_list pop ']'                     // CFA, nested type / tuple field selector
    486                 { throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; }                                                          // FIX ME
     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
     491generic_assoc_list:                                                                             // C11
     492        | generic_association
     493        | generic_assoc_list ',' generic_association
     494        ;
     495
     496generic_association:                                                                    // C11
     497        type_no_function ':' assignment_expression
     498        | DEFAULT ':' assignment_expression
    487499        ;
    488500
     
    767779        | unary_expression assignment_operator assignment_expression
    768780                { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); }
     781        | unary_expression '=' '{' initializer_list comma_opt '}' // FIX ME
     782                { $$ = nullptr; }
    769783        ;
    770784
     
    10501064        | RETURN comma_expression_opt ';'
    10511065                { $$ = new StatementNode( build_return( $2 ) ); }
     1066        | RETURN '{' initializer_list comma_opt '}'                     // FIX ME
     1067                { $$ = nullptr; }
    10521068        | THROW assignment_expression_opt ';'                           // handles rethrow
    10531069                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    10681084mutex_statement:
    10691085        MUTEX '(' argument_expression_list ')' statement
    1070                 { throw SemanticError("Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME
     1086                { throw SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
    10711087        ;
    10721088
     
    12891305static_assert:
    12901306        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1291                 { throw SemanticError("Static assert is currently unimplemented."); $$ = nullptr; }     // FIX ME
     1307                { throw SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; }   // FIX ME
    12921308
    12931309// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    23772393                {
    23782394                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    2379                         linkage = LinkageSpec::linkageUpdate( linkage, $2 );
     2395                        linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
    23802396                }
    23812397          '{' external_definition_list_opt '}'
  • src/ResolvExpr/AlternativeFinder.cc

    rc71b256 r7c782af  
    239239                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
    240240                        )
    241                         throw SemanticError( "No reasonable alternatives for expression ", expr );
     241                        throw SemanticError( expr, "No reasonable alternatives for expression " );
    242242                }
    243243                if ( prune ) {
     
    257257                                stream << "Alternatives are:\n";
    258258                                printAlts( winners, stream, 1 );
    259                                 throw SemanticError( stream.str() );
     259                                throw SemanticError( expr->location, stream.str() );
    260260                        }
    261261                        alternatives = move(pruned);
     
    494494                                return;
    495495                        } else if ( level >= recursionLimit ) {
    496                                 throw SemanticError( "Too many recursive assertions" );
     496                                throw SemanticError( newAlt.expr->location, "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( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
     1410                                throw SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
    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( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() );
     1431                                throw SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
    14321432                        } // if
    14331433                        // return the lowest cost alternative for the argument
  • src/ResolvExpr/CurrentObject.cc

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

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

    rc71b256 r7c782af  
    443443                        // isomorphic to C type-compatibility, which it may not be.
    444444                        if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
    445                                 throw SemanticError( "conflicting overload of C function ", decl );
     445                                throw SemanticError( decl, "conflicting overload of C function " );
    446446                        }
    447447                } else {
    448448                        // Check that a Cforall declaration doesn't override any C declaration
    449449                        if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    450                                 throw SemanticError( "Cforall declaration hides C function ", decl );
     450                                throw SemanticError( decl, "Cforall declaration hides C function " );
    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( msg, decl ); return true; }, baseExpr );
     465                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); 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( msg, decl ); return true; }, nullptr, deleteStmt );
     470                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
    471471        }
    472472
     
    477477                        return true;
    478478                } else {
    479                         throw SemanticError( "redeclaration of ", added );
     479                        throw SemanticError( added, "redeclaration of " );
    480480                }
    481481        }
     
    504504                        return false;
    505505                } else if ( ! added->get_members().empty() ) {
    506                         throw SemanticError( "redeclaration of ", added );
     506                        throw SemanticError( added, "redeclaration of " );
    507507                } // if
    508508                return true;
  • src/SymTab/Validate.cc

    rc71b256 r7c782af  
    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( "invalid type void in function type ", func );
     363                                throw SemanticError( func, "invalid type void in function type " );
    364364                        }
    365365
     
    402402                for ( Expression * param : inst->parameters ) {
    403403                        if ( ! dynamic_cast< TypeExpr * >( param ) ) {
    404                                 throw SemanticError( "Expression parameters for generic types are currently unsupported: ", inst );
     404                                throw SemanticError( inst, "Expression parameters for generic types are currently unsupported: " );
    405405                        }
    406406                }
     
    502502                TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
    503503                if ( ! traitDecl ) {
    504                         throw SemanticError( "use of undeclared trait " + traitInst->name );
     504                        throw SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
    505505                } // if
    506506                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
    507                         throw SemanticError( "incorrect number of trait parameters: ", traitInst );
     507                        throw SemanticError( traitInst, "incorrect number of trait parameters: " );
    508508                } // if
    509509                traitInst->baseTrait = traitDecl;
     
    513513                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
    514514                        if ( ! expr ) {
    515                                 throw SemanticError( "Expression parameters for trait instances are currently unsupported: ", std::get<1>(p) );
     515                                throw SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
    516516                        }
    517517                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
     
    619619                                bool isVoid = fixFunction( assertion );
    620620                                if ( isVoid ) {
    621                                         throw SemanticError( "invalid type void in assertion of function ", node );
     621                                        throw SemanticError( node, "invalid type void in assertion of function " );
    622622                                } // if
    623623                        } // for
     
    663663                // were cast to void.
    664664                if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) {
    665                         throw SemanticError( "Non-void function returns no values: " , returnStmt );
     665                        throw SemanticError( returnStmt, "Non-void function returns no values: " );
    666666                }
    667667        }
     
    704704                                ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
    705705                                if ( ! rtt ) {
    706                                         throw SemanticError("Cannot apply type parameters to base type of " + typeInst->name);
     706                                        throw SemanticError( typeInst->location, "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( "Cannot redefine typedef: " + tyDecl->name );
     744                                throw SemanticError( tyDecl->location, "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( "Cannot redefine typedef: " + tyDecl->name );
     751                                throw SemanticError( tyDecl->location, "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(), Type::StorageClasses(), type, aggDecl->get_linkage() ) );
     849                        TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, 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( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
     900                                throw SemanticError( funcDecl, "Constructors, destructors, and assignment functions require at least one parameter " );
    901901                        }
    902902                        ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
    903903                        if ( ! refType ) {
    904                                 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl );
     904                                throw SemanticError( funcDecl, "First parameter of a constructor, destructor, or assignment function must be a reference " );
    905905                        }
    906906                        if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
    907                                 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
     907                                throw SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values " );
    908908                        }
    909909                }
     
    940940
    941941                        sub.apply( inst );
    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 );
     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 " );
    944944                }
    945945        }
  • src/SynTree/Declaration.h

    rc71b256 r7c782af  
    245245        typedef NamedTypeDecl Parent;
    246246  public:
    247         TypedefDecl( const std::string &name, Type::StorageClasses scs, Type *type, LinkageSpec::Spec spec = LinkageSpec::Cforall ) : Parent( name, scs, type ) { set_linkage( spec ); }
     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
    248250        TypedefDecl( const TypedefDecl &other ) : Parent( other ) {}
    249251
  • src/SynTree/Expression.cc

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

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

    rc71b256 r7c782af  
    100100        //actually this is a syntactic error signaled by the parser
    101101        if ( type == BranchStmt::Goto && target.empty() ) {
    102                 throw SemanticError("goto without target");
     102                throw SemanticError( target.get_statement()->location, "goto without target");
    103103        }
    104104}
     
    107107        Statement(), computedTarget( computedTarget ), type( type ) {
    108108        if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
    109                 throw SemanticError("Computed target not valid in branch statement");
     109                throw SemanticError( computedTarget->location, "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("default case with condition: ", condition);
     205        if ( isDefault() && condition != 0 ) throw SemanticError( condition, "default case with condition: " );
    206206}
    207207
  • src/SynTree/TypeSubstitution.h

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

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

    rc71b256 r7c782af  
    1818#include <stdio.h>
    1919#include <string.h>
    20 #include <time.h>
    2120#include <unistd.h>
    2221#include <sys/time.h>
     
    2726#include "preemption.h"
    2827
    29 //=============================================================================================
    30 // time type
    31 //=============================================================================================
    3228
    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 
    40 void ?{}( __cfa_time_t & this ) { this.val = 0; }
    41 void ?{}( __cfa_time_t & this, zero_t zero ) { this.val = 0; }
    42 
    43 void ?{}( 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
     29static 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
    4632        it_interval.tv_sec = 0;
    4733        it_interval.tv_usec = 0;
    4834}
    4935
    50 
    51 void ?{}( __cfa_time_t & this, timespec * curr ) {
     36static inline void ?{}( __cfa_time_t & this, timespec * curr ) {
    5237        uint64_t secs  = curr->tv_sec;
    5338        uint64_t nsecs = curr->tv_nsec;
    54         this.val = (secs * one_second) + nsecs;
     39        this.val = from_s(secs).val + nsecs;
    5540}
    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; }
    6641
    6742//=============================================================================================
     
    8459//=============================================================================================
    8560
    86 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) {
     61void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) {
    8762        this.thrd = thrd;
    8863        this.alarm = alarm;
     
    9368}
    9469
    95 void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) {
     70void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) {
    9671        this.proc = proc;
    9772        this.alarm = alarm;
  • src/libcfa/concurrency/alarm.h

    rc71b256 r7c782af  
    2121#include <assert.h>
    2222
     23#include "bits/cfatime.h"
     24
    2325struct thread_desc;
    2426struct processor;
    25 
    26 struct timespec;
    27 struct itimerval;
    28 
    29 //=============================================================================================
    30 // time type
    31 //=============================================================================================
    32 
    33 struct __cfa_time_t {
    34         uint64_t val;
    35 };
    36 
    37 // ctors
    38 void ?{}( __cfa_time_t & this );
    39 void ?{}( __cfa_time_t & this, zero_t zero );
    40 void ?{}( __cfa_time_t & this, timespec * curr );
    41 void ?{}( itimerval & this, __cfa_time_t * alarm );
    42 
    43 __cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs );
    44 
    45 // logical ops
    46 static inline bool ?==?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val == rhs.val; }
    47 static inline bool ?!=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val != rhs.val; }
    48 static inline bool ?>? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >  rhs.val; }
    49 static inline bool ?<? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <  rhs.val; }
    50 static inline bool ?>=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >= rhs.val; }
    51 static inline bool ?<=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <= rhs.val; }
    52 
    53 static inline bool ?==?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val == rhs; }
    54 static inline bool ?!=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val != rhs; }
    55 static inline bool ?>? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >  rhs; }
    56 static inline bool ?<? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <  rhs; }
    57 static inline bool ?>=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >= rhs; }
    58 static inline bool ?<=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <= rhs; }
    59 
    60 // addition/substract
    61 static 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 
    67 static 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 
    78 extern __cfa_time_t zero_time;
    7927
    8028//=============================================================================================
     
    10553typedef alarm_node_t ** __alarm_it_t;
    10654
    107 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
    108 void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
     55void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s );
     56void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s );
    10957void ^?{}( alarm_node_t & this );
    11058
  • src/libcfa/concurrency/coroutine.c

    rc71b256 r7c782af  
    9999// Wrapper for co
    100100void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
     101        verify( preemption.enabled || this_processor->do_terminate );
    101102        disable_interrupts();
    102103
     
    116117
    117118        enable_interrupts( __cfaabi_dbg_ctx );
     119        verify( preemption.enabled || this_processor->do_terminate );
    118120} //ctxSwitchDirect
    119121
  • src/libcfa/concurrency/invoke.c

    rc71b256 r7c782af  
    2828extern void __suspend_internal(void);
    2929extern void __leave_coroutine(void);
     30extern void __finish_creation(void);
    3031extern void __leave_thread_monitor( struct thread_desc * this );
    3132extern void disable_interrupts();
     
    4445
    4546        cor->state = Active;
     47
     48        enable_interrupts( __cfaabi_dbg_ctx );
    4649
    4750        main( this );
     
    6265        // First suspend, once the thread arrives here,
    6366        // the function pointer to main can be invalidated without risk
    64         __suspend_internal();
     67        __finish_creation();
    6568
    6669        // Fetch the thread handle from the user defined thread structure
  • src/libcfa/concurrency/kernel.c

    rc71b256 r7c782af  
    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;
     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
     62volatile thread_local __cfa_kernel_preemption_data_t preemption = { false, false, 1 };
    6163
    6264//-----------------------------------------------------------------------------
     
    207209                        if(readyThread)
    208210                        {
    209                                 verify( !preemption_enabled );
     211                                verify( !preemption.enabled );
    210212
    211213                                runThread(this, readyThread);
    212214
    213                                 verify( !preemption_enabled );
     215                                verify( !preemption.enabled );
    214216
    215217                                //Some actions need to be taken from the kernel
     
    260262void finishRunning(processor * this) with( this->finish ) {
    261263        if( action_code == Release ) {
    262                 verify( !preemption_enabled );
     264                verify( !preemption.enabled );
    263265                unlock( *lock );
    264266        }
     
    267269        }
    268270        else if( action_code == Release_Schedule ) {
    269                 verify( !preemption_enabled );
     271                verify( !preemption.enabled );
    270272                unlock( *lock );
    271273                ScheduleThread( thrd );
    272274        }
    273275        else if( action_code == Release_Multi ) {
    274                 verify( !preemption_enabled );
     276                verify( !preemption.enabled );
    275277                for(int i = 0; i < lock_count; i++) {
    276278                        unlock( *locks[i] );
     
    304306        this_coroutine = NULL;
    305307        this_thread = NULL;
    306         preemption_enabled = false;
    307         disable_preempt_count = 1;
     308        preemption.enabled = false;
     309        preemption.disable_count = 1;
    308310        // SKULLDUGGERY: We want to create a context for the processor coroutine
    309311        // which is needed for the 2-step context switch. However, there is no reason
     
    345347}
    346348
     349void 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
    347387//-----------------------------------------------------------------------------
    348388// Scheduler routines
     
    352392        verify( thrd->self_cor.state != Halted );
    353393
    354         verify( !preemption_enabled );
     394        verify( !preemption.enabled );
    355395
    356396        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
     
    362402        }
    363403
    364         verify( !preemption_enabled );
     404        verify( !preemption.enabled );
    365405}
    366406
    367407thread_desc * nextThread(cluster * this) with( *this ) {
    368         verify( !preemption_enabled );
     408        verify( !preemption.enabled );
    369409        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    370410        thread_desc * head = pop_head( ready_queue );
    371411        unlock( ready_queue_lock );
    372         verify( !preemption_enabled );
     412        verify( !preemption.enabled );
    373413        return head;
    374414}
     
    376416void BlockInternal() {
    377417        disable_interrupts();
    378         verify( !preemption_enabled );
     418        verify( !preemption.enabled );
    379419        returnToKernel();
    380         verify( !preemption_enabled );
     420        verify( !preemption.enabled );
    381421        enable_interrupts( __cfaabi_dbg_ctx );
    382422}
     
    387427        this_processor->finish.lock        = lock;
    388428
    389         verify( !preemption_enabled );
     429        verify( !preemption.enabled );
    390430        returnToKernel();
    391         verify( !preemption_enabled );
     431        verify( !preemption.enabled );
    392432
    393433        enable_interrupts( __cfaabi_dbg_ctx );
     
    399439        this_processor->finish.thrd        = thrd;
    400440
    401         verify( !preemption_enabled );
     441        verify( !preemption.enabled );
    402442        returnToKernel();
    403         verify( !preemption_enabled );
     443        verify( !preemption.enabled );
    404444
    405445        enable_interrupts( __cfaabi_dbg_ctx );
     
    413453        this_processor->finish.thrd        = thrd;
    414454
    415         verify( !preemption_enabled );
     455        verify( !preemption.enabled );
    416456        returnToKernel();
    417         verify( !preemption_enabled );
     457        verify( !preemption.enabled );
    418458
    419459        enable_interrupts( __cfaabi_dbg_ctx );
     
    426466        this_processor->finish.lock_count  = count;
    427467
    428         verify( !preemption_enabled );
     468        verify( !preemption.enabled );
    429469        returnToKernel();
    430         verify( !preemption_enabled );
     470        verify( !preemption.enabled );
    431471
    432472        enable_interrupts( __cfaabi_dbg_ctx );
     
    441481        this_processor->finish.thrd_count  = thrd_count;
    442482
    443         verify( !preemption_enabled );
     483        verify( !preemption.enabled );
    444484        returnToKernel();
    445         verify( !preemption_enabled );
     485        verify( !preemption.enabled );
    446486
    447487        enable_interrupts( __cfaabi_dbg_ctx );
     
    449489
    450490void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    451         verify( !preemption_enabled );
     491        verify( !preemption.enabled );
    452492        this_processor->finish.action_code = thrd ? Release_Schedule : Release;
    453493        this_processor->finish.lock        = lock;
     
    463503// Kernel boot procedures
    464504void kernel_startup(void) {
     505        verify( !preemption.enabled );
    465506        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    466507
     
    500541        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    501542        // mainThread is on the ready queue when this call is made.
    502         resume( *mainProcessor->runner );
     543        kernel_first_resume( this_processor );
    503544
    504545
     
    507548        __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n");
    508549
     550        verify( !preemption.enabled );
    509551        enable_interrupts( __cfaabi_dbg_ctx );
     552        verify( preemption.enabled );
    510553}
    511554
     
    513556        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    514557
     558        verify( preemption.enabled );
    515559        disable_interrupts();
     560        verify( !preemption.enabled );
    516561
    517562        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
  • src/libcfa/concurrency/kernel_private.h

    rc71b256 r7c782af  
    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;
     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
     80struct __cfa_kernel_preemption_data_t {
     81        bool enabled;
     82        bool in_progress;
     83        unsigned short disable_count;
     84};
     85
     86extern volatile thread_local __cfa_kernel_preemption_data_t preemption;
    7987
    8088//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor.c

    rc71b256 r7c782af  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:12:20 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Feb 16 14:49:53 2018
     13// Update Count     : 5
    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 %li got %li", &this, 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 );
    430430                }
    431431
  • src/libcfa/concurrency/preemption.c

    rc71b256 r7c782af  
    149149        // Disable interrupts by incrementing the counter
    150150        void disable_interrupts() {
    151                 preemption_enabled = false;
    152                 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1;
    153                 disable_preempt_count = new_val;
     151                preemption.enabled = false;
     152                __attribute__((unused)) unsigned short new_val = preemption.disable_count + 1;
     153                preemption.disable_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 = disable_preempt_count;
    164                 disable_preempt_count -= 1;
     163                unsigned short prev = preemption.disable_count;
     164                preemption.disable_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 = disable_preempt_count;
    184                 disable_preempt_count -= 1;
     183                unsigned short prev = preemption.disable_count;
     184                preemption.disable_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         disable_preempt_count = 1;
     252        preemption.enabled = false;
     253        preemption.disable_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, zero_time, zero_time };
     292        (this.alarm){ proc, 0`cfa_s, 0`cfa_s };
    293293        this.proc = proc;
    294294        this.proc->preemption_alarm = &this.alarm;
     
    300300        disable_interrupts();
    301301
    302         update_preemption( this.proc, zero_time );
     302        update_preemption( this.proc, 0`cfa_s );
    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

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

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

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

    rc71b256 r7c782af  
    1010// Created On       : Wed Feb  3 07:56:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 22 21:26:40 2018
    13 // Update Count     : 326
     12// Last Modified On : Fri Feb 16 15:42:31 2018
     13// Update Count     : 330
    1414//
    1515
     
    2727int main( void ) {
    2828        size_t dim = 10;
     29        char fill = '\xff';
    2930        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 %#x\n", fill );
     81        printf( "CFA array alloc, fill %#hhx\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

    rc71b256 r7c782af  
    1 raii/dtor-early-exit.c:220:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)
     1raii/dtor-early-exit.c:217: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.