Changes in / [c71b256:7c782af]
- Files:
-
- 1 added
- 49 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
rc71b256 r7c782af 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Sun Feb 4 10:38:26201814 %% Update Count : 36 513 %% Last Modified On : Tue Feb 13 08:19:07 2018 14 %% Update Count : 367 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 177 177 \makeatother 178 178 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}% 181 181 \item\relax 182 182 }{% 183 183 \endlist 184 }% quote2184 }% cquote 185 185 186 186 \newenvironment{rationale}{% 187 \begin{ quote2}\noindent$\Box$\enspace187 \begin{cquote}\noindent$\Box$\enspace 188 188 }{% 189 \hfill\enspace$\Box$\end{ quote2}189 \hfill\enspace$\Box$\end{cquote} 190 190 }% 191 191 … … 201 201 \newenvironment{syntax}{ 202 202 \paragraph{Syntax} 203 \begin{ quote2}203 \begin{cquote} 204 204 \begin{description}[noitemsep,leftmargin=\parindentlnth] 205 205 }{ 206 206 \end{description} 207 \end{ quote2}207 \end{cquote} 208 208 } 209 209 % \def\syntax{\paragraph{Syntax}\trivlist\parindent=.5in\item[\hskip.5in]} -
doc/papers/general/Paper.tex
rc71b256 r7c782af 4 4 \usepackage{epic,eepic} 5 5 \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 8 10 \usepackage{rotating} 9 11 \usepackage[usenames]{color} 10 \usepackage{pslatex} % reduce size of san serif font12 \usepackage{pslatex} % reduce size of san serif font 11 13 \usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref} 12 14 13 15 \setlength{\textheight}{9in} 14 16 %\oddsidemargin 0.0in 15 \renewcommand{\topfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page16 \renewcommand{\bottomfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page17 \renewcommand{\floatpagefraction}{0.8} % float must be greater than X of the page before it is forced onto its own page18 \renewcommand{\textfraction}{0.0} % the entire page maybe devoted to floats with no text on the page at all19 20 \lefthyphenmin=4 % hyphen only after 4 characters17 \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 21 23 \righthyphenmin=4 22 24 … … 24 26 25 27 \newcommand{\CFAIcon}{\textsf{C}\raisebox{\depth}{\rotatebox{180}{\textsf{A}}}\xspace} % Cforall symbolic name 26 \newcommand{\CFA}{\protect\CFAIcon} % safe for section/caption27 \newcommand{\CFL}{\textrm{Cforall}\xspace} % Cforall symbolic name28 \newcommand{\Celeven}{\textrm{C11}\xspace} % C11 symbolic name28 \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 29 31 \newcommand{\CC}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}\xspace} % C++ symbolic name 30 32 \newcommand{\CCeleven}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name … … 56 58 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 57 59 58 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly60 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly 59 61 \newlength{\columnposn} 60 62 \setlength{\gcolumnposn}{2.75in} … … 72 74 73 75 % Latin abbreviation 74 \newcommand{\abbrevFont}{\textit} % set empty for no italics76 \newcommand{\abbrevFont}{\textit} % set empty for no italics 75 77 \newcommand{\EG}{\abbrevFont{e}.\abbrevFont{g}.} 76 78 \newcommand*{\eg}{% … … 103 105 104 106 \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}% 106 108 \item\relax 107 109 }{% … … 187 189 188 190 189 \section{Introduction and Background}191 \section{Introduction} 190 192 191 193 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects. … … 193 195 The 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. 194 196 The top 3 rankings over the past 30 years are: 195 \lstDeleteShortInline@%196 197 \begin{center} 197 198 \setlength{\tabcolsep}{10pt} 199 \lstDeleteShortInline@% 198 200 \begin{tabular}{@{}rccccccc@{}} 199 201 & 2017 & 2012 & 2007 & 2002 & 1997 & 1992 & 1987 \\ \hline … … 202 204 \CC & 3 & 3 & 3 & 3 & 2 & 2 & 4 \\ 203 205 \end{tabular} 206 \lstMakeShortInline@% 204 207 \end{center} 205 \lstMakeShortInline@%206 208 Love it or hate it, C is extremely popular, highly used, and one of the few systems languages. 207 209 In many cases, \CC is often used solely as a better C. … … 224 226 The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance. 225 227 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 234 C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax. 235 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C. 236 Code generation for these overloaded functions and variables is implemented by the usual approach of mangling the identifier names to include a representation of their type, while \CFA decides which overload to apply based on the same ``usual arithmetic conversions'' used in C to disambiguate operator overloads. 237 As an example: 238 239 \begin{cfa} 240 int max(int a, int b) { return a < b ? b : a; } // (1) 241 double max(double a, double b) { return a < b ? b : a; } // (2) 242 243 int max = INT_MAX; // (3) 244 double max = DBL_MAX; // (4) 245 246 max(7, -max); $\C{// uses (1) and (3), by matching int from constant 7}$ 247 max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$ 248 249 //max(max, -max); $\C{// ERROR: ambiguous}$ 250 int m = max(max, -max); $\C{// uses (1) once and (3) twice, by matching return type}$ 251 \end{cfa} 252 253 \Celeven did add @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 254 The macro wrapping the generic expression imposes some limitations; as an example, it could not implement the example above, because the variables @max@ would collide with the functions @max@. 255 Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the functions dispatched to, which must all have distinct names. 256 257 \subsection{\texorpdfstring{\LstKeywordStyle{forall} Functions}{forall Functions}} 228 258 \label{sec:poly-fns} 229 259 230 \CFA{}\hspace{1pt}'s polymorphism was originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.231 260 The 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): 232 261 \begin{lstlisting} … … 257 286 Crucial to the design of a new programming language are the libraries to access thousands of external software features. 258 287 Like \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 float ing-pointarray:288 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array: 260 289 \begin{lstlisting} 261 290 void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, … … 263 292 int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 : 264 293 *(double *)t2 < *(double *)t1 ? 1 : 0; } 265 double key = 5.0, vals[10] = { /* 10 sorted float ing-pointvalues */ };294 double key = 5.0, vals[10] = { /* 10 sorted float values */ }; 266 295 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ 267 296 \end{lstlisting} … … 304 333 Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types. 305 334 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@. 312 343 313 344 \subsection{Traits} … … 505 536 In many languages, functions can return at most one value; 506 537 however, 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 float ing-pointvalues, respectively.538 Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively. 508 539 \begin{lstlisting} 509 540 typedef struct { int quo, rem; } div_t; $\C{// from include stdlib.h}$ … … 936 967 937 968 \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. 938 971 939 972 … … 1044 1077 The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed. 1045 1078 1079 1046 1080 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}} 1047 1081 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 1082 There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses. 1083 1084 C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}. 1085 \CFA provides a shorthand for a non-contiguous list: 1086 \begin{cquote} 1087 \lstDeleteShortInline@% 1088 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1089 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1090 \begin{cfa} 1091 case 2, 10, 34, 42: 1092 \end{cfa} 1093 & 1094 \begin{cfa} 1095 case 2: case 10: case 34: case 42: 1096 \end{cfa} 1097 \end{tabular} 1098 \lstMakeShortInline@% 1099 \end{cquote} 1100 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1101 \begin{cquote} 1102 \lstDeleteShortInline@% 1103 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1104 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1105 \begin{cfa} 1106 case 2~42: 1107 \end{cfa} 1108 & 1109 \begin{cfa} 1110 case 2: case 3: ... case 41: case 42: 1111 \end{cfa} 1112 \end{tabular} 1113 \lstMakeShortInline@% 1114 \end{cquote} 1115 and a combination: 1116 \begin{cfa} 1117 case -12~-4, -1~5, 14~21, 34~42: 1118 \end{cfa} 1119 1120 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1121 \begin{cfa} 1122 switch ( i ) { 1123 case 0: 1124 for ( int i = 0; i < 10; i += 1 ) { 1125 ... 1126 `case 1:` // no initialization of loop index 1127 ... 1128 } 1129 } 1130 \end{cfa} 1131 \CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality. 1132 1133 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1134 \begin{cfa} 1135 switch ( x ) { 1136 `int y = 1;` $\C{// unreachable initialization}$ 1137 `x = 7;` $\C{// unreachable code without label/branch}$ 1138 case 0: 1139 ... 1140 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1141 z = 2; 1142 case 1: 1143 `x = z;` $\C{// without fall through, z is undefined}$ 1144 } 1145 \end{cfa} 1146 \CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses, but no statements. 1147 \CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred. 1148 1149 C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through}; 1150 @case@ clauses are made disjoint by the @break@ statement. 1151 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements. 1152 \CFA provides a new control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through: 1153 \begin{cquote} 1154 \lstDeleteShortInline@% 1155 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1156 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1157 \begin{cfa} 1158 `choose` ( day ) { 1159 case Mon~Thu: 1160 // program 1161 1162 case Fri: 1163 // program 1164 wallet += pay; 1165 `fallthrough;` 1166 case Sat: 1167 // party 1168 wallet -= party; 1169 1170 case Sun: 1171 // rest 1172 1173 default: 1174 // error 1175 } 1176 \end{cfa} 1177 & 1178 \begin{cfa} 1179 switch ( day ) { 1180 case Mon: case Tue: case Wed: case Thu: 1181 // program 1182 `break;` 1183 case Fri: 1184 // program 1185 wallet += pay; 1186 1187 case Sat: 1188 // party 1189 wallet -= party; 1190 `break;` 1191 case Sun: 1192 // rest 1193 `break;` 1194 default: 1195 // error 1196 } 1197 \end{cfa} 1198 \end{tabular} 1199 \lstMakeShortInline@% 1200 \end{cquote} 1201 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1202 1203 \begin{comment} 1052 1204 Forgotten @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. 1053 1205 \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. … … 1070 1222 } 1071 1223 \end{cfa} 1224 \end{comment} 1225 1072 1226 1073 1227 \subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}} … … 1206 1360 \end{cfa} 1207 1361 1208 1209 \subsection{Exception Handling ???} 1210 1362 % \subsection{Exception Handling ???} 1211 1363 1212 1364 \section{Declarations} … … 1255 1407 \lstDeleteShortInline@% 1256 1408 \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}} \\ 1259 1411 \begin{cfa} 1260 1412 +[5] *+ `int` x1; 1261 1413 +* [5]+ `int` x2; 1262 +[* [5] int]+ f`( int p )`;1414 `[* [5] int]` f+( int p )+; 1263 1415 \end{cfa} 1264 1416 & … … 1266 1418 `int` +*+ x1 +[5]+; 1267 1419 `int` +(*+x2+)[5]+; 1268 +int (*+f`( int p )`+)[5]+;1420 `int (*`f+( int p )+`)[5]`; 1269 1421 \end{cfa} 1270 1422 \end{tabular} … … 1277 1429 \begin{cquote} 1278 1430 \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}} \\ 1281 1433 \begin{cfa} 1282 1434 `*` int x, y; … … 1292 1444 \begin{cquote} 1293 1445 \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}} \\ 1296 1448 \begin{cfa} 1297 1449 `*` int x; … … 1310 1462 \begin{cquote} 1311 1463 \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}} \\ 1314 1466 \begin{cfa} 1315 1467 [ 5 ] int z; … … 1351 1503 \begin{cquote} 1352 1504 \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}} \\ 1355 1507 \begin{cfa} 1356 1508 const * const int x; … … 1374 1526 \begin{cquote} 1375 1527 \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}} \\ 1378 1530 \begin{cfa} 1379 1531 extern [ 5 ] int x; … … 1397 1549 \begin{cquote} 1398 1550 \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}} \\ 1401 1553 \begin{cfa} 1402 1554 y = (* int)x; … … 1415 1567 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style. 1416 1568 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems. 1569 1570 The syntax of the new routine prototype declaration follows directly from the new routine definition syntax; 1571 as well, parameter names are optional, \eg: 1572 \begin{cfa} 1573 [ int x ] f (); $\C{// returning int with no parameters}$ 1574 [ * int ] g (int y); $\C{// returning pointer to int with int parameter}$ 1575 [ ] h ( int, char ); $\C{// returning no result with int and char parameters}$ 1576 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$ 1577 \end{cfa} 1578 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa). 1579 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list, \eg: 1580 \begin{cquote} 1581 \lstDeleteShortInline@% 1582 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1583 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1584 \begin{cfa} 1585 [double] foo(), foo( int ), foo( double ) {...} 1586 \end{cfa} 1587 & 1588 \begin{cfa} 1589 double foo1(), foo2( int ), foo3( double ); 1590 \end{cfa} 1591 \end{tabular} 1592 \lstMakeShortInline@% 1593 \end{cquote} 1594 \CFA allows the last routine in the list to define its body. 1595 1596 Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg: 1597 \begin{cfa} 1598 extern [ int ] f ( int ); 1599 static [ int ] g ( int ); 1600 \end{cfa} 1601 1602 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg: 1603 \begin{cfa} 1604 * [ int x ] () fp; $\C{// pointer to routine returning int with no parameters}$ 1605 * [ * int ] (int y) gp; $\C{// pointer to routine returning pointer to int with int parameter}$ 1606 * [ ] (int,char) hp; $\C{// pointer to routine returning no result with int and char parameters}$ 1607 * [ * int,int ] ( int ) jp; $\C{// pointer to routine returning pointer to int and int, with int parameter}$ 1608 \end{cfa} 1609 While parameter names are optional, \emph{a routine name cannot be specified}; 1610 for example, the following is incorrect: 1611 \begin{cfa} 1612 * [ int x ] f () fp; $\C{// routine name "f" is not allowed}$ 1613 \end{cfa} 1417 1614 1418 1615 … … 1593 1790 In 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. 1594 1791 1792 1793 \subsection{Type Nesting} 1794 1795 \CFA allows \newterm{type nesting}, and type qualification of the nested types (see Figure~\ref{f:TypeNestingQualification}), where as C hoists (refactors) nested types into the enclosing scope and has no type qualification. 1796 \begin{figure} 1797 \centering 1798 \lstDeleteShortInline@% 1799 \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}} 1800 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}} & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}} & \multicolumn{1}{|c}{\textbf{\CFA}} \\ 1801 \hline 1802 \begin{cfa} 1803 struct S { 1804 enum C { R, G, B }; 1805 struct T { 1806 union U { int i, j; }; 1807 enum C c; 1808 short int i, j; 1809 }; 1810 struct T t; 1811 } s; 1812 1813 int rtn() { 1814 s.t.c = R; 1815 struct T t = { R, 1, 2 }; 1816 enum C c; 1817 union U u; 1818 } 1819 \end{cfa} 1820 & 1821 \begin{cfa} 1822 enum C { R, G, B }; 1823 union U { int i, j; }; 1824 struct T { 1825 enum C c; 1826 short int i, j; 1827 }; 1828 struct S { 1829 struct T t; 1830 } s; 1831 1832 1833 1834 1835 1836 1837 1838 \end{cfa} 1839 & 1840 \begin{cfa} 1841 struct S { 1842 enum C { R, G, B }; 1843 struct T { 1844 union U { int i, j; }; 1845 enum C c; 1846 short int i, j; 1847 }; 1848 struct T t; 1849 } s; 1850 1851 int rtn() { 1852 s.t.c = `S.`R; // type qualification 1853 struct `S.`T t = { `S.`R, 1, 2 }; 1854 enum `S.`C c; 1855 union `S.T.`U u; 1856 } 1857 \end{cfa} 1858 \end{tabular} 1859 \lstMakeShortInline@% 1860 \caption{Type Nesting / Qualification} 1861 \label{f:TypeNestingQualification} 1862 \end{figure} 1863 In the left example in C, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope. 1864 In the right example in \CFA, the types are not hoisted and accessed using the field-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@''. 1865 1866 1595 1867 \subsection{Default Parameters} 1596 1868 … … 1598 1870 \section{Literals} 1599 1871 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 float ing-pointtypes are very similar, differing from each other only in suffix.1872 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix. 1601 1873 In 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. 1602 1874 … … 1622 1894 struct Weight { double stones; }; 1623 1895 1624 void ?{}( Weight & w ) { w.stones = 0; } 1896 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$ 1625 1897 void ?{}( Weight & w, double w ) { w.stones = w; } 1626 1898 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } … … 1631 1903 1632 1904 int main() { 1633 Weight w, hw = { 14 }; $\C{// 14 stone}$1905 Weight w, hw = { 14 }; $\C{// 14 stone}$ 1634 1906 w = 11@`st@ + 1@`lb@; 1635 1907 w = 70.3@`kg@; 1636 1908 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)}$ 1639 1911 w = 5@`st@ + 8@`kg@ + 25@`lb@ + hw; 1640 1912 } 1641 1913 \end{cfa} 1642 1914 }% 1915 1916 1917 \section{Libraries} 1918 \label{sec:libraries} 1919 1920 As stated in Section~\ref{sec:poly-fns}, \CFA inherits a large corpus of library code, where other programming languages must rewrite or provide fragile inter-language communication with C. 1921 \CFA has replacement libraries condensing hundreds of existing C names into tens of \CFA overloaded names, all without rewriting the actual computations. 1922 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime. 1923 The following sections give a glimpse of the interface reduction to many C libraries. 1924 In many cases, @signed@/@unsigned@ @char@ and @short@ routines are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results. 1925 1926 1927 \subsection{Limits} 1928 1929 C library @limits.h@ provides lower and upper bound constants for the basic types. 1930 \CFA name overloading is used to condense these typed constants, \eg: 1931 \begin{cquote} 1932 \lstDeleteShortInline@% 1933 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1934 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\ 1935 \begin{cfa} 1936 const short int `MIN` = -32768; 1937 const int `MIN` = -2147483648; 1938 const long int `MIN` = -9223372036854775808L; 1939 \end{cfa} 1940 & 1941 \begin{cfa} 1942 short int si = `MIN`; 1943 int i = `MIN`; 1944 long int li = `MIN`; 1945 \end{cfa} 1946 \end{tabular} 1947 \lstMakeShortInline@% 1948 \end{cquote} 1949 The result is a significant reduction in names to access typed constants, \eg: 1950 \begin{cquote} 1951 \lstDeleteShortInline@% 1952 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1953 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1954 \begin{cfa} 1955 MIN 1956 MAX 1957 M_PI 1958 M_E 1959 \end{cfa} 1960 & 1961 \begin{cfa} 1962 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, 1963 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, 1964 M_PI, M_PIl, M_CPI, M_CPIl, 1965 M_E, M_El, M_CE, M_CEl 1966 \end{cfa} 1967 \end{tabular} 1968 \lstMakeShortInline@% 1969 \end{cquote} 1970 1971 1972 \subsection{Math} 1973 1974 C library @math.h@ provides many mathematical routines. 1975 \CFA routine overloading is used to condense these mathematical routines, \eg: 1976 \begin{cquote} 1977 \lstDeleteShortInline@% 1978 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1979 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\ 1980 \begin{cfa} 1981 float `log`( float x ); 1982 double `log`( double ); 1983 double _Complex `log`( double _Complex x ); 1984 \end{cfa} 1985 & 1986 \begin{cfa} 1987 float f = `log`( 3.5 ); 1988 double d = `log`( 3.5 ); 1989 double _Complex dc = `log`( 3.5+0.5I ); 1990 \end{cfa} 1991 \end{tabular} 1992 \lstMakeShortInline@% 1993 \end{cquote} 1994 The result is a significant reduction in names to access math routines, \eg: 1995 \begin{cquote} 1996 \lstDeleteShortInline@% 1997 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1998 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1999 \begin{cfa} 2000 log 2001 sqrt 2002 sin 2003 \end{cfa} 2004 & 2005 \begin{cfa} 2006 logf, log, logl, clogf, clog, clogl 2007 sqrtf, sqrt, sqrtl, csqrtf, csqrt, csqrtl 2008 sinf, sin, sinl, csinf, csin, csinl 2009 \end{cfa} 2010 \end{tabular} 2011 \lstMakeShortInline@% 2012 \end{cquote} 2013 While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a routine name with a single set of floating type(s). 2014 For example, it is not possible to overload @atan@ for both one and two arguments; 2015 instead the names @atan@ and @atan2@ are required. 2016 The key observation is that only a restricted set of type-generic macros are provided for a limited set of routine names, which do not generalize across the type system, as in \CFA. 2017 2018 2019 \subsection{Standard} 2020 2021 C library @stdlib.h@ provides many general routines. 2022 \CFA routine overloading is used to condense these utility routines, \eg: 2023 \begin{cquote} 2024 \lstDeleteShortInline@% 2025 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2026 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Definition}} & \multicolumn{1}{c}{\textbf{Usage}} \\ 2027 \begin{cfa} 2028 unsigned int `abs`( int ); 2029 double `abs`( double ); 2030 double abs( double _Complex ); 2031 \end{cfa} 2032 & 2033 \begin{cfa} 2034 unsigned int i = `abs`( -1 ); 2035 double d = `abs`( -1.5 ); 2036 double d = `abs`( -1.5+0.5I ); 2037 \end{cfa} 2038 \end{tabular} 2039 \lstMakeShortInline@% 2040 \end{cquote} 2041 The result is a significant reduction in names to access utility routines, \eg: 2042 \begin{cquote} 2043 \lstDeleteShortInline@% 2044 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2045 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2046 \begin{cfa} 2047 abs 2048 strto 2049 random 2050 \end{cfa} 2051 & 2052 \begin{cfa} 2053 abs, labs, llabs, fabsf, fabs, fabsl, cabsf, cabs, cabsl 2054 strtol, strtoul, strtoll, strtoull, strtof, strtod, strtold 2055 srand48, mrand48, lrand48, drand48 2056 \end{cfa} 2057 \end{tabular} 2058 \lstMakeShortInline@% 2059 \end{cquote} 2060 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@. 2061 2062 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety. 2063 C/\Celeven provide a number of complex and overlapping storage-management operation to support the following capabilities: 2064 \begin{description}[itemsep=2pt,parsep=0pt] 2065 \item[fill] 2066 after allocation the storage is filled with a specified character. 2067 \item[resize] 2068 an existing allocation is decreased or increased in size. 2069 In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied. 2070 For an increase in storage size, new storage after the copied data may be filled. 2071 \item[alignment] 2072 an allocation starts on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes. 2073 \item[array] 2074 the allocation size is scaled to the specified number of array elements. 2075 An array may be filled, resized, or aligned. 2076 \end{description} 2077 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-routines and how all the capabilities can be combined into two \CFA routines. 2078 2079 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2080 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety: 2081 \begin{cquote} 2082 \begin{cfa}[aboveskip=0pt] 2083 size_t dim = 10; $\C{// array dimension}$ 2084 char fill = '\xff'; $\C{// initialization fill value}$ 2085 int * ip; 2086 \end{cfa} 2087 \lstDeleteShortInline@% 2088 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2089 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2090 \begin{cfa} 2091 ip = alloc(); 2092 ip = alloc( fill ); 2093 ip = alloc( dim ); 2094 ip = alloc( dim, fill ); 2095 ip = alloc( ip, 2 * dim ); 2096 ip = alloc( ip, 4 * dim, fill ); 2097 2098 ip = align_alloc( 16 ); 2099 ip = align_alloc( 16, fill ); 2100 ip = align_alloc( 16, dim ); 2101 ip = align_alloc( 16, dim, fill ); 2102 \end{cfa} 2103 & 2104 \begin{cfa} 2105 ip = (int *)malloc( sizeof( int ) ); 2106 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2107 ip = (int *)malloc( dim * sizeof( int ) ); 2108 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2109 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2110 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2111 2112 ip = memalign( 16, sizeof( int ) ); 2113 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2114 ip = memalign( 16, dim * sizeof( int ) ); 2115 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2116 \end{cfa} 2117 \end{tabular} 2118 \lstMakeShortInline@% 2119 \end{cquote} 2120 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2121 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg: 2122 \begin{cfa} 2123 struct S { int i, j; }; 2124 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2125 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2126 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2127 \end{cfa} 2128 Note, \CC can only initialization array elements via the default constructor. 2129 2130 Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap. 2131 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2132 2133 \begin{table} 2134 \centering 2135 \lstDeleteShortInline@% 2136 \lstMakeShortInline~% 2137 \begin{tabular}{@{}r|r|l|l|l|l@{}} 2138 \multicolumn{1}{c}{}& & \multicolumn{1}{c|}{fill} & resize & alignment & array \\ 2139 \hline 2140 C & ~malloc~ & no & no & no & no \\ 2141 & ~calloc~ & yes (0 only) & no & no & yes \\ 2142 & ~realloc~ & no/copy & yes & no & no \\ 2143 & ~memalign~ & no & no & yes & no \\ 2144 & ~posix_memalign~ & no & no & yes & no \\ 2145 \hline 2146 C11 & ~aligned_alloc~ & no & no & yes & no \\ 2147 \hline 2148 \CFA & ~alloc~ & yes/copy & no/yes & no & yes \\ 2149 & ~align_alloc~ & yes & no & yes & yes \\ 2150 \end{tabular} 2151 \lstDeleteShortInline~% 2152 \lstMakeShortInline@% 2153 \caption{Storage-Management Operations} 2154 \label{t:StorageManagementOperations} 2155 \end{table} 2156 2157 2158 \subsection{I/O} 2159 \label{s:IOLibrary} 2160 2161 The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user defined types in a consistent way. 2162 The approach combines ideas from \CC and Python. 2163 The \CFA header file for the I/O library is @fstream@. 2164 2165 The common case is printing out a sequence of variables separated by whitespace. 2166 \begin{cquote} 2167 \lstDeleteShortInline@% 2168 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2169 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 2170 \begin{cfa} 2171 int x = 1, y = 2, z = 3; 2172 sout | x `|` y `|` z | endl; 2173 \end{cfa} 2174 & 2175 \begin{cfa} 2176 2177 cout << x `<< " "` << y `<< " "` << z << endl; 2178 \end{cfa} 2179 \\ 2180 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 2181 1` `2` `3 2182 \end{cfa} 2183 & 2184 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt] 2185 1 2 3 2186 \end{cfa} 2187 \end{tabular} 2188 \lstMakeShortInline@% 2189 \end{cquote} 2190 The \CFA form has half the characters of the \CC form, and is similar to Python I/O with respect to implicit separators. 2191 Similar simplification occurs for tuple I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''. 2192 \begin{cfa} 2193 [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ]; 2194 sout | t1 | t2 | endl; $\C{// print tuples}$ 2195 \end{cfa} 2196 \begin{cfa}[showspaces=true,aboveskip=0pt] 2197 1`, `2`, `3 4`, `5`, `6 2198 \end{cfa} 2199 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment. 2200 Therefore, fewer output expressions require parenthesis. 2201 \begin{cquote} 2202 \lstDeleteShortInline@% 2203 \begin{tabular}{@{}ll@{}} 2204 \textbf{\CFA:} 2205 & 2206 \begin{cfa} 2207 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl; 2208 \end{cfa} 2209 \\ 2210 \textbf{\CC:} 2211 & 2212 \begin{cfa} 2213 cout << x * 3 << y + 1 << `(`z << 2`)` << `(`x == y`)` << (x | y) << (x || y) << (x > z ? 1 : 2) << endl; 2214 \end{cfa} 2215 \\ 2216 \textbf{output:} 2217 & 2218 \begin{cfa}[showspaces=true,aboveskip=0pt] 2219 3 3 12 0 3 1 2 2220 \end{cfa} 2221 \end{tabular} 2222 \lstMakeShortInline@% 2223 \end{cquote} 2224 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output. 2225 2226 The implicit separator character (space/blank) is a separator not a terminator. 2227 The rules for implicitly adding the separator are: 2228 \begin{itemize}[itemsep=2pt,parsep=0pt] 2229 \item 2230 A separator does not appear at the start or end of a line. 2231 \item 2232 A separator does not appear before or after a character literal or variable. 2233 \item 2234 A separator does not appear before or after a null (empty) C string, which is a local mechanism to disable insertion of the separator character. 2235 \item 2236 A separator does not appear before a C string starting with the characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$@ 2237 \item 2238 A seperator does not appear after a C string ending with the characters: \lstinline[basicstyle=\tt]@,.;!?)]}%@ 2239 \item 2240 {\lstset{language=CFA,deletedelim=**[is][]{`}{`}} 2241 A seperator does not appear before or after a C string begining/ending with the quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@ 2242 }% 2243 \item 2244 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output. 2245 \end{itemize} 2246 2247 2248 \subsection{Multi-precision Integers} 2249 \label{s:MultiPrecisionIntegers} 2250 2251 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP. 2252 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers. 2253 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@. 2254 The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces. 2255 \begin{cquote} 2256 \lstDeleteShortInline@% 2257 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}@{\hspace{\parindentlnth}}l@{}} 2258 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\ 2259 \begin{cfa} 2260 #include <gmp> 2261 int main( void ) { 2262 sout | "Factorial Numbers" | endl; 2263 Int fact = 1; 2264 2265 sout | 0 | fact | endl; 2266 for ( unsigned int i = 1; i <= 40; i += 1 ) { 2267 fact *= i; 2268 sout | i | fact | endl; 2269 } 2270 } 2271 \end{cfa} 2272 & 2273 \begin{cfa} 2274 #include <gmp.h> 2275 int main( void ) { 2276 `gmp_printf`( "Factorial Numbers\n" ); 2277 `mpz_t` fact; 2278 `mpz_init_set_ui`( fact, 1 ); 2279 `gmp_printf`( "%d %Zd\n", 0, fact ); 2280 for ( unsigned int i = 1; i <= 40; i += 1 ) { 2281 `mpz_mul_ui`( fact, fact, i ); 2282 `gmp_printf`( "%d %Zd\n", i, fact ); 2283 } 2284 } 2285 \end{cfa} 2286 \end{tabular} 2287 \lstMakeShortInline@% 2288 \end{cquote} 2289 1643 2290 1644 2291 \section{Evaluation} … … 1704 2351 1705 2352 \begin{table} 2353 \centering 1706 2354 \caption{Properties of benchmark code} 1707 2355 \label{tab:eval} -
doc/user/user.tex
rc71b256 r7c782af 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Wed Jan 31 22:29:25201814 %% Update Count : 31 4713 %% Last Modified On : Tue Feb 13 08:31:21 2018 14 %% Update Count : 3161 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 161 161 Like \Index*[C++]{\CC{}}, there may be both an old and new ways to achieve the same effect. 162 162 For 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} 164 164 \begin{tabular}{@{}l@{\hspace{1.5em}}l@{\hspace{1.5em}}l@{}} 165 165 \multicolumn{1}{c@{\hspace{1.5em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ … … 191 191 \end{cfa} 192 192 \end{tabular} 193 \end{ quote2}193 \end{cquote} 194 194 While 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}). 195 195 … … 274 274 275 275 \begin{comment} 276 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating -pointarray:276 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array: 277 277 \begin{lstlisting} 278 278 void * bsearch( const void * key, const void * base, size_t dim, size_t size, … … 282 282 *(double *)t2 < *(double *)t1 ? 1 : 0; } 283 283 284 double key = 5.0, vals[10] = { /* 10 sorted floating -pointvalues */ };284 double key = 5.0, vals[10] = { /* 10 sorted floating values */ }; 285 285 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ 286 286 \end{lstlisting} … … 444 444 0x®_®ff®_®ff; §\C{// hexadecimal constant}§ 445 445 0x®_®ef3d®_®aa5c; §\C{// hexadecimal constant}§ 446 3.141®_®592®_®654; §\C{// floating pointconstant}§447 10®_®e®_®+1®_®00; §\C{// floating pointconstant}§448 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating point}§449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating pointlong constant}§446 3.141®_®592®_®654; §\C{// floating constant}§ 447 10®_®e®_®+1®_®00; §\C{// floating constant}§ 448 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating}§ 449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating long constant}§ 450 450 L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§ 451 451 \end{cfa} … … 501 501 \label{f:HeaderFileInterposition} 502 502 \end{figure} 503 504 505 \section{Exponentiation Operator} 506 507 C, \CC, and Java (and many other programming languages) have no exponentiation operator\index{exponentiation!operator}\index{operator!exponentiation}, \ie $x^y$, and instead use a routine, like \Indexc{pow}, to perform the exponentiation operation. 508 \CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@\lstinline$?\?$} and ©?\=?©\index{?\\=?@\lstinline$?\=?$}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$. 509 The priority of the exponentiation operator is between the cast and multiplicative operators, so that ©w * (int)x \ (int)y * z© is parenthesized as ©((w * (((int)x) \ ((int)y))) * z)©. 510 511 As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types. 512 Unsigned integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the base is 2). 513 Signed integral exponentiation\index{exponentiation!signed integral} is performed with repeated multiplication (or shifting if the base is 2), but yields a floating result because $x^{-y}=1/x^y$. 514 Hence, it is important to designate exponent integral-constants as unsigned or signed: ©3 \ 3u© return an integral result, while ©3 \ 3© returns a floating result. 515 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative. 516 \begin{cfa} 517 sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl; 518 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i 519 \end{cfa} 520 Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©. 521 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available. 522 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©; 523 for returning a floating value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents. 503 524 504 525 … … 628 649 \end{cfa} 629 650 The 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} 631 652 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 632 653 \begin{cfa} … … 656 677 \end{cfa} 657 678 \end{tabular} 658 \end{ quote2}679 \end{cquote} 659 680 In this example, case 2 is always done if case 3 is done. 660 681 This 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. … … 730 751 ®int y = 1;® §\C{// unreachable initialization}§ 731 752 ®x = 7;® §\C{// unreachable code without label/branch}§ 732 case 3: ...753 case 0: ... 733 754 ... 734 755 ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§ 735 756 z = 2; 736 case 3:757 case 1: 737 758 ®x = z;® §\C{// without fall through, z is uninitialized}§ 738 759 } … … 819 840 Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C. 820 841 Therefore, the ©case© clause is extended with a list of values, as in: 821 \begin{ quote2}842 \begin{cquote} 822 843 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 823 844 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 849 870 \end{cfa} 850 871 \end{tabular} 851 \end{ quote2}872 \end{cquote} 852 873 In addition, two forms of subranges are allowed to specify case values: a new \CFA form and an existing GNU C form.\footnote{ 853 874 The GNU C form \emph{requires} spaces around the ellipse.} 854 \begin{ quote2}875 \begin{cquote} 855 876 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 856 877 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{GNU C}} \\ … … 882 903 \end{cfa} 883 904 \end{tabular} 884 \end{ quote2}905 \end{cquote} 885 906 Lists of subranges are also allowed. 886 907 \begin{cfa} … … 902 923 } 903 924 \end{C++} 904 Since CFA is non-object-oriented, the equivalent object-oriented program looks like:925 Since \CFA is non-object-oriented, the equivalent object-oriented program looks like: 905 926 \begin{cfa} 906 927 struct S { int i, j; }; 907 int mem( S & ®this® ) { §\C{// explicit "this" parameter}§928 int mem( S & ®this® ) { §\C{// explicit "this" parameter}§ 908 929 ®this.®i = 1; §\C{// "this" is not elided}§ 909 930 ®this.®j = 2; 910 931 } 911 932 \end{cfa} 912 but it is cumbersome having to write "©this.©"many times in a member.933 but it is cumbersome having to write ``©this.©'' many times in a member. 913 934 914 935 \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. 915 936 \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}§937 int mem( S & this ) ®with this® { §\C{// with clause}§ 938 i = 1; §\C{\color{red}// this.i}§ 939 j = 2; §\C{\color{red}// this.j}§ 919 940 } 920 941 \end{cfa} … … 922 943 \begin{cfa} 923 944 struct T { double m, n; }; 924 int mem2( S & this1, T &this2 ) ®with this1, this2® {945 int mem2( S & this1, T & this2 ) ®with this1, this2® { 925 946 i = 1; j = 2; 926 947 m = 1.0; n = 2.0; … … 933 954 struct S1 { ... } s1; 934 955 struct S2 { ... } s2; 935 ®with s1® { // with statement956 ®with s1® { §\C{// with statement}§ 936 957 // access fields of s1 without qualification 937 ®with s2® { // nesting958 ®with s2® { §\C{// nesting}§ 938 959 // access fields of s1 and s2 without qualification 939 960 } … … 1045 1066 1046 1067 1047 \section{ Declarations}1048 \label{s: Declarations}1068 \section{Alternative Declarations} 1069 \label{s:AlternativeDeclarations} 1049 1070 1050 1071 C declaration syntax is notoriously confusing and error prone. 1051 1072 For example, many C programmers are confused by a declaration as simple as: 1052 \begin{ quote2}1073 \begin{cquote} 1053 1074 \begin{tabular}{@{}ll@{}} 1054 1075 \begin{cfa} … … 1058 1079 \raisebox{-0.75\totalheight}{\input{Cdecl}} 1059 1080 \end{tabular} 1060 \end{ quote2}1081 \end{cquote} 1061 1082 Is 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.1083 If there is any doubt, it implies \Index{productivity} and \Index{safety} issues even for basic programs. 1063 1084 Another 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. 1064 1085 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: 1065 1086 \begin{cfa} 1066 int ®(*®f®())[®5®]® {...}; §\C{ definition}§1067 ... ®(*®f®())[®3®]® += 1; §\C{ usage}§1087 int ®(*®f®())[®5®]® {...}; §\C{// definition}§ 1088 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§ 1068 1089 \end{cfa} 1069 1090 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}). … … 1074 1095 In the following example, \R{red} is the base type and \B{blue} is qualifiers. 1075 1096 The \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} 1077 1098 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1078 1099 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1089 1110 \end{cfa} 1090 1111 \end{tabular} 1091 \end{ quote2}1112 \end{cquote} 1092 1113 The only exception is \Index{bit field} specification, which always appear to the right of the base type. 1093 1114 % 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. 1094 1115 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1095 1116 For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows: 1096 \begin{ quote2}1117 \begin{cquote} 1097 1118 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1098 1119 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1105 1126 \end{cfa} 1106 1127 \end{tabular} 1107 \end{ quote2}1128 \end{cquote} 1108 1129 The downside of this semantics is the need to separate regular and \Index{pointer} declarations: 1109 \begin{ quote2}1130 \begin{cquote} 1110 1131 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1111 1132 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1120 1141 \end{cfa} 1121 1142 \end{tabular} 1122 \end{ quote2}1143 \end{cquote} 1123 1144 which is \Index{prescribing} a safety benefit. 1124 1145 Other examples are: 1125 \begin{ quote2}1146 \begin{cquote} 1126 1147 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1127 1148 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 1159 1180 \end{cfa} 1160 1181 \end{tabular} 1161 \end{ quote2}1182 \end{cquote} 1162 1183 1163 1184 All 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} 1165 1186 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 1166 1187 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\ … … 1180 1201 \end{cfa} 1181 1202 \end{tabular} 1182 \end{ quote2}1203 \end{cquote} 1183 1204 All 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} 1184 1205 The 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} 1186 1207 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1187 1208 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 1201 1222 \end{cfa} 1202 1223 \end{tabular} 1203 \end{ quote2}1224 \end{cquote} 1204 1225 1205 1226 The 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} 1207 1228 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1208 1229 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1209 1230 \begin{cfa} 1210 y = ( ®* int®)x;1211 i = sizeof( ®[ 5 ] * int®);1231 y = (* int)x; 1232 i = sizeof([ 5 ] * int); 1212 1233 \end{cfa} 1213 1234 & 1214 1235 \begin{cfa} 1215 y = ( ®int *®)x;1216 i = sizeof( ®int * [ 5 ]®);1236 y = (int *)x; 1237 i = sizeof(int * [ 5 ]); 1217 1238 \end{cfa} 1218 1239 \end{tabular} 1219 \end{ quote2}1240 \end{cquote} 1220 1241 1221 1242 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration. 1222 1243 Therefore, 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. 1244 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems. 1245 1245 1246 1246 … … 1260 1260 A program \newterm{object} is a region of data storage in the execution environment, the contents of which can represent values. 1261 1261 In 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} 1263 1263 \begin{tabular}{@{}ll@{\hspace{2em}}l@{}} 1264 1264 \begin{cfa} … … 1278 1278 \end{cfa} 1279 1279 \end{tabular} 1280 \end{ quote2}1280 \end{cquote} 1281 1281 where the right example is how the compiler logically interprets the variables in the left example. 1282 1282 Since a variable name only points to one address during its lifetime, it is an \Index{immutable} \Index{pointer}; … … 1284 1284 In general, variable addresses are stored in instructions instead of loaded from memory, and hence may not occupy storage. 1285 1285 These approaches are contrasted in the following: 1286 \begin{ quote2}1286 \begin{cquote} 1287 1287 \begin{tabular}{@{}l|l@{}} 1288 1288 \multicolumn{1}{c|}{explicit variable address} & \multicolumn{1}{c}{implicit variable address} \\ … … 1302 1302 \end{cfa} 1303 1303 \end{tabular} 1304 \end{ quote2}1304 \end{cquote} 1305 1305 Finally, 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. 1306 1306 Therefore, 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}. … … 1309 1309 (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.) 1310 1310 Hence, 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} 1312 1312 \begin{tabular}{@{}l@{\hspace{2em}}l@{}} 1313 1313 \begin{cfa} … … 1321 1321 \raisebox{-0.5\totalheight}{\input{pointer2.pstex_t}} 1322 1322 \end{tabular} 1323 \end{ quote2}1323 \end{cquote} 1324 1324 1325 1325 Notice, an address has a \Index{duality}\index{address!duality}: a location in memory or the value at that location. … … 1426 1426 The position of the ©const© qualifier \emph{after} the pointer/reference qualifier causes confuse for C programmers. 1427 1427 The ©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} 1430 1430 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1431 1431 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1440 1440 \end{cfa} 1441 1441 \end{tabular} 1442 \end{ quote2}1442 \end{cquote} 1443 1443 where the \CFA declaration is read left-to-right. 1444 1444 … … 1518 1518 \begin{cfa} 1519 1519 void f( int i ); 1520 void (* fp)( int ); §\C{// routine pointer}§1520 void (* fp)( int ); §\C{// routine pointer}§ 1521 1521 fp = f; §\C{// reference initialization}§ 1522 1522 fp = &f; §\C{// pointer initialization}§ … … 1897 1897 \end{cfa} 1898 1898 This 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:1899 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:AlternativeDeclarations}), \eg: 1900 1900 \begin{cfa} 1901 1901 C : const double bar1(), bar2( int ), bar3( double ); … … 2072 2072 Default arguments and overloading (see Section 24) are complementary. 2073 2073 While in theory default arguments can be simulated with overloading, as in: 2074 \begin{ quote2}2074 \begin{cquote} 2075 2075 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 2076 2076 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{default arguments}} & \multicolumn{1}{c}{\textbf{overloading}} \\ … … 2087 2087 \end{cfa} 2088 2088 \end{tabular} 2089 \end{ quote2}2089 \end{cquote} 2090 2090 the number of required overloaded routines is linear in the number of default values, which is unacceptable growth. 2091 2091 In general, overloading should only be used over default arguments if the body of the routine is significantly different. … … 2224 2224 The following program in undefined in \CFA (and Indexc{gcc}) 2225 2225 \begin{cfa} 2226 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§2226 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§ 2227 2227 int ®i® = 7; 2228 2228 int bar( int p ) { … … 2233 2233 } 2234 2234 int main() { 2235 * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§2235 * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§ 2236 2236 sout | fp( 3 ) | endl; 2237 2237 } … … 2272 2272 In the latter approach, additional return values are passed as pointer parameters. 2273 2273 A 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 -pointvalue.2274 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value. 2275 2275 \begin{cfa} 2276 2276 double modf( double x, double * i ); §\C{// from include math.h}§ … … 2995 2995 2996 2996 The common case is printing out a sequence of variables separated by whitespace. 2997 \begin{ quote2}2997 \begin{cquote} 2998 2998 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 2999 2999 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ … … 3016 3016 \end{cfa} 3017 3017 \end{tabular} 3018 \end{ quote2}3018 \end{cquote} 3019 3019 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators. 3020 3020 Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''. … … 3028 3028 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment. 3029 3029 Therefore, fewer output expressions require parenthesis. 3030 \begin{ quote2}3030 \begin{cquote} 3031 3031 \begin{tabular}{@{}ll@{}} 3032 3032 \textbf{\CFA:} … … 3047 3047 \end{cfa} 3048 3048 \end{tabular} 3049 \end{ quote2}3049 \end{cquote} 3050 3050 There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output. 3051 3051 … … 3420 3420 int id; 3421 3421 float size; 3422 Parts * optionalParts;3422 Parts * optionalParts; 3423 3423 }; 3424 3424 … … 3634 3634 3635 3635 Auto 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} 3637 3637 \begin{tabular}{@{}l@{\hspace{3em}}ll@{}} 3638 3638 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{\Indexc{gcc}}} \\ … … 3658 3658 \end{cfa} 3659 3659 \end{tabular} 3660 \end{ quote2}3660 \end{cquote} 3661 3661 The two important capabilities are: 3662 3662 \begin{itemize} … … 3806 3806 3807 3807 generic(type T) 3808 typedef int (* predicate)(T);3808 typedef int (* predicate)(T); 3809 3809 generic(type Captured, type T) 3810 typedef void (* callback)(Captured, T);3810 typedef void (* callback)(Captured, T); 3811 3811 3812 3812 generic(type T) 3813 void find(int length, T * array,3813 void find(int length, T * array, 3814 3814 predicate(T) p, callback(void *, T)f) { 3815 3815 int i; … … 3835 3835 struct LinkedListElem { 3836 3836 T elem; 3837 LinkedListElem(T) * next;3837 LinkedListElem(T) * next; 3838 3838 }; 3839 3839 3840 LinkedListElem *++?(LinkedListElem ** elem) {3841 return * elem = elem->next;3840 LinkedListElem *++?(LinkedListElem ** elem) { 3841 return * elem = elem->next; 3842 3842 } 3843 3843 3844 3844 generic (type T) 3845 3845 struct LinkedList { 3846 LinkedListElem(T) * head;3846 LinkedListElem(T) * head; 3847 3847 unsigned int size; 3848 3848 } 3849 3849 3850 3850 generic (type T | bool ?==?(T, T)) 3851 bool contains(LinkedList(T) * list, T elem) {3852 for(LinkedListElem * iter = list->head; iter != 0; ++iter) {3851 bool contains(LinkedList(T) * list, T elem) { 3852 for(LinkedListElem * iter = list->head; iter != 0; ++iter) { 3853 3853 if (iter->elem == elem) return true; 3854 3854 } … … 4063 4063 // transferring requires mutual exclusion and calls deleteJob 4064 4064 4065 void transferJob(mutex Worker & from, Worker &to) {4065 void transferJob(mutex Worker & from, Worker & to) { 4066 4066 ... 4067 4067 deleteJob(j); … … 5001 5001 #include <unistd.h> 5002 5002 } 5003 size_t fileSize( const char * path ) {5003 size_t fileSize( const char * path ) { 5004 5004 struct stat s; 5005 5005 stat(path, &s); … … 5038 5038 #[link(name = "libc")] 5039 5039 extern { 5040 fn stat(path: * const u8,5041 buf: * mut stat_t) -> c_int;5042 } 5043 fn fileSize(path: * const u8) -> size_t5040 fn stat(path: * const u8, 5041 buf: * mut stat_t) -> c_int; 5042 } 5043 fn fileSize(path: * const u8) -> size_t 5044 5044 { 5045 5045 unsafe { … … 5063 5063 generic(type T, type N | 5064 5064 { int ?<?(N, N); }) 5065 T * maximize(N (*f)(const T&),5065 T * maximize(N (*f)(const T&), 5066 5066 int n, T *a) { 5067 T * bestX = NULL;5067 T * bestX = NULL; 5068 5068 N bestN; 5069 5069 for (int i = 0; i < n; i++) { … … 5077 5077 } 5078 5078 5079 string * longest(int n, string *p)5079 string * longest(int n, string *p) 5080 5080 { 5081 5081 return maximize(length, n, p); … … 5085 5085 \begin{cfa} 5086 5086 template<typename T, typename F> 5087 T * maximize(const F &f,5087 T * maximize(const F &f, 5088 5088 int n, T *a) { 5089 5089 typedef decltype(f(a[0])) N; 5090 T * bestX = NULL;5090 T * bestX = NULL; 5091 5091 N bestN; 5092 5092 for (int i = 0; i < n; i++) { … … 5100 5100 } 5101 5101 5102 string * longest(int n, string *p) {5102 string * longest(int n, string *p) { 5103 5103 return maximize( 5104 5104 [](const string &s) { … … 5258 5258 \begin{cfa} 5259 5259 task Nonzero { 5260 int * data;5260 int * data; 5261 5261 int start; 5262 5262 int end; … … 5721 5721 \CFA introduces the following new keywords. 5722 5722 5723 \begin{ quote2}5723 \begin{cquote} 5724 5724 \input{../refrat/keywords} 5725 \end{ quote2}5725 \end{cquote} 5726 5726 5727 5727 … … 5730 5730 5731 5731 \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} 5733 5733 \begin{tabular}{@{}llllll|l@{}} 5734 5734 \multicolumn{6}{c|}{C11} & \multicolumn{1}{c}{\CFA} \\ … … 5790 5790 \end{tabular} 5791 5791 \end{tabular} 5792 \end{ quote2}5792 \end{cquote} 5793 5793 For the prescribed head-files, \CFA uses header interposition to wraps these includes in an ©extern "C"©; 5794 5794 hence, names in these include files are not mangled\index{mangling!name} (see~\VRef{s:Interoperability}). … … 6531 6531 The following factorial programs contrast using GMP with the \CFA and C interfaces, where the output from these programs appears in \VRef[Figure]{f:MultiPrecisionFactorials}. 6532 6532 (Compile with flag \Indexc{-lgmp} to link with the GMP library.) 6533 \begin{ quote2}6533 \begin{cquote} 6534 6534 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}} 6535 6535 \multicolumn{1}{c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\ … … 6563 6563 \end{cfa} 6564 6564 \end{tabular} 6565 \end{ quote2}6565 \end{cquote} 6566 6566 6567 6567 \begin{figure} -
src/CodeGen/FixMain.cc
rc71b256 r7c782af 39 39 { 40 40 if(main_signature) { 41 throw SemanticError( "Multiple definition of main routine\n", functionDecl);41 throw SemanticError(functionDecl, "Multiple definition of main routine\n"); 42 42 } 43 43 main_signature.reset( functionDecl->clone() ); -
src/CodeGen/FixNames.cc
rc71b256 r7c782af 118 118 int nargs = functionDecl->get_functionType()->get_parameters().size(); 119 119 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"); 121 121 } 122 122 functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) ); -
src/Common/PassVisitor.impl.h
rc71b256 r7c782af 77 77 maybeAccept_impl( *i, visitor ); 78 78 } catch( SemanticError &e ) { 79 e.set_location( (*i)->location );80 79 errors.append( e ); 81 80 } … … 104 103 maybeMutate_impl( *i, mutator ); 105 104 } catch( SemanticError &e ) { 106 e.set_location( (*i)->location );107 105 errors.append( e ); 108 106 } … … 134 132 } 135 133 } catch( SemanticError &e ) { 136 e.set_location( (*i)->location );137 134 errors.append( e ); 138 135 } … … 163 160 } // if 164 161 } catch( SemanticError &e ) { 165 e.set_location( (*i)->location );166 162 errors.append( e ); 167 163 } // try … … 200 196 201 197 } catch ( SemanticError &e ) { 202 e.set_location( (*i)->location );203 198 errors.append( e ); 204 199 } -
src/Common/SemanticError.cc
rc71b256 r7c782af 23 23 #include "SemanticError.h" 24 24 25 SemanticError::SemanticError() { 26 } 27 28 SemanticError::SemanticError( std::string error ) { 29 append( error ); 25 SemanticError::SemanticError( CodeLocation location, std::string error ) { 26 append( location, error ); 30 27 } 31 28 … … 34 31 } 35 32 36 void SemanticError::append( const std::string & msg ) {37 errors.emplace_back( error_str() +msg );33 void SemanticError::append( CodeLocation location, const std::string & msg ) { 34 errors.emplace_back( location, msg ); 38 35 } 39 36 … … 42 39 } 43 40 44 void SemanticError::print( std::ostream &os) {41 void SemanticError::print() { 45 42 using std::to_string; 46 43 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; 48 45 } 49 46 } 50 47 51 void SemanticError::set_location( const CodeLocation& location) {52 errors.begin()->maybeSet( location );48 SemanticWarning::SemanticWarning( CodeLocation location, std::string msg ) { 49 std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl; 53 50 } 54 51 -
src/Common/SemanticError.h
rc71b256 r7c782af 24 24 #include "CodeLocation.h" // for CodeLocation, toString 25 25 26 //----------------------------------------------------------------------------- 27 // Errors 26 28 struct error { 29 CodeLocation location; 27 30 std::string description; 28 CodeLocation location;29 31 30 32 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 ) {} 38 34 }; 39 35 40 36 class SemanticError : public std::exception { 41 37 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 ); 45 40 ~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); 46 45 47 46 static inline const std::string & error_str() { … … 51 50 52 51 void append( SemanticError & other ); 53 void append( const std::string & );52 void append( CodeLocation location, const std::string & ); 54 53 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(); 60 55 private: 61 56 std::list< error > errors; … … 63 58 64 59 template< typename T > 65 SemanticError::SemanticError( const std::string & error, const T * obj ) { 66 append( toString( error, obj ) ); 60 SemanticError::SemanticError( const T * obj, const std::string & error ) 61 : SemanticError( obj->location, toString( error, obj ) ) 62 {} 63 64 template< typename T > 65 SemanticError::SemanticError( CodeLocation location, const T * obj, const std::string & error ) 66 : SemanticError( location, toString( error, obj ) ) 67 {} 68 69 //----------------------------------------------------------------------------- 70 // Warnings 71 class SemanticWarning { 72 public: 73 SemanticWarning( CodeLocation location, std::string error ); 74 ~SemanticWarning() throw() {} 75 76 // constructs an exception using the given message and the printed representation of the obj (T must have a print method) 77 template< typename T > SemanticWarning(const T * obj, const std::string & error); 78 template< typename T > SemanticWarning( CodeLocation location, const T * obj, const std::string & error); 79 80 static inline const std::string & warning_str() { 81 static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: "; 82 return str; 83 } 84 85 private: 86 }; 87 88 template< typename T > 89 SemanticWarning::SemanticWarning( const T * obj, const std::string & error ) 90 : SemanticWarning( obj->location, toString( error, obj ) ) 91 {} 92 93 template< typename T > 94 SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error ) 95 : SemanticWarning( location, toString( error, obj ) ) 96 {} 97 98 //----------------------------------------------------------------------------- 99 // Helpers 100 static inline const std::string & bold_ttycode() { 101 static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : ""; 102 return str; 103 } 104 105 static inline const std::string & reset_font_ttycode() { 106 static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : ""; 107 return str; 108 } 109 110 static inline std::string make_bold( const std::string & str ) { 111 return bold_ttycode() + str + reset_font_ttycode(); 112 } 113 114 struct bold {}; 115 static inline std::ostream & operator<<(std::ostream & os, bold) { 116 os << bold_ttycode(); 117 return os; 118 } 119 120 struct reset_font {}; 121 static inline std::ostream & operator<<(std::ostream & os, reset_font) { 122 os << reset_font_ttycode(); 123 return os; 67 124 } 68 125 -
src/Concurrency/Keywords.cc
rc71b256 r7c782af 276 276 handle( decl ); 277 277 } 278 279 278 } 280 279 … … 282 281 if( ! decl->body ) return; 283 282 284 if( !type_decl ) throw SemanticError( context_error, decl);283 if( !type_decl ) throw SemanticError( decl, context_error ); 285 284 286 285 FunctionDecl * func = forwardDeclare( decl ); … … 419 418 if( mutexArgs.empty() ) return; 420 419 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" ); 422 421 423 422 bool isDtor = CodeGen::isDestructor( decl->name ); 424 423 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" ); 426 425 427 426 for(auto arg : mutexArgs) { … … 432 431 if( ! body ) return; 433 432 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>" ); 437 436 438 437 if( isDtor ) { … … 480 479 //Makes sure it's not a copy 481 480 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 " ); 483 482 484 483 //Make sure the we are pointing directly to a type 485 484 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 " ); 488 487 489 488 //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 " ); 491 490 } 492 491 … … 626 625 if( type && type->get_baseStruct()->is_thread() ) { 627 626 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>"); 629 628 } 630 629 -
src/Concurrency/Waitfor.cc
rc71b256 r7c782af 249 249 250 250 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>" ); 252 253 253 254 CompoundStmt * stmt = new CompoundStmt(); -
src/ControlStruct/ExceptTranslate.cc
rc71b256 r7c782af 572 572 // Pass. 573 573 } 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"); 575 575 } else { 576 throw SemanticError( "catchResume must have exception type");576 throw SemanticError(catchStmt->location, "catchResume must have exception type"); 577 577 } 578 578 -
src/ControlStruct/LabelFixer.cc
rc71b256 r7c782af 92 92 } else if ( labelTable[ l ]->defined() ) { 93 93 // 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() ); 95 95 } else { 96 96 // used previously, but undefined until now -> link with this entry … … 121 121 for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) { 122 122 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() ); 124 124 } 125 125 (*ret)[ i->first ] = i->second->get_definition(); -
src/ControlStruct/MLEMutator.cc
rc71b256 r7c782af 115 115 } else { 116 116 // 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" ); 118 118 targetEntry = enclosingControlStructures.rbegin(); 119 119 } // if … … 124 124 // ensure that selected target is valid 125 125 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 ) ); 127 127 } // if 128 128 break; -
src/GenPoly/Box.cc
rc71b256 r7c782af 229 229 } // if 230 230 } catch( SemanticError &e ) { 231 e.set_location( (*i)->location );232 231 errors.append( e ); 233 232 } // try … … 576 575 } 577 576 } 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: " ); 579 578 } 580 579 } … … 598 597 } else { 599 598 // 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 " ) ); 601 600 } // if 602 601 } // if -
src/InitTweak/FixInit.cc
rc71b256 r7c782af 282 282 translationUnit.splice( i, fixer.pass.staticDtorDecls ); 283 283 } catch( SemanticError &e ) { 284 e.set_location( (*i)->location );285 284 errors.append( e ); 286 285 } // try … … 895 894 ) 896 895 if ( ! diff.empty() ) { 897 throw SemanticError( st d::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() + " " ); 898 897 } // if 899 898 // S_G-S_L results in set of objects that must be destructed … … 1111 1110 template< typename Visitor, typename... Params > 1112 1111 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... ) ); 1115 1113 v.errors.append( err ); 1116 1114 } -
src/InitTweak/GenInit.cc
rc71b256 r7c782af 317 317 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) { 318 318 // 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" ); 320 320 // 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 " ); 322 322 323 323 objDecl->set_init( genCtorInit( objDecl ) ); -
src/InitTweak/InitTweak.cc
rc71b256 r7c782af 225 225 // xxx - this shouldn't be an error, but need a way to 226 226 // terminate without creating output, so should catch this error 227 throw SemanticError( "unbalanced list initializers" );227 throw SemanticError( init->location, "unbalanced list initializers" ); 228 228 } 229 229 -
src/Parser/DeclarationNode.cc
rc71b256 r7c782af 581 581 dst->basictype = src->basictype; 582 582 } 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: " ); 584 584 585 585 if ( dst->complextype == DeclarationNode::NoComplexType ) { 586 586 dst->complextype = src->complextype; 587 587 } 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: " ); 589 589 590 590 if ( dst->signedness == DeclarationNode::NoSignedness ) { 591 591 dst->signedness = src->signedness; 592 592 } 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: " ); 594 594 595 595 if ( dst->length == DeclarationNode::NoLength ) { … … 598 598 dst->length = DeclarationNode::LongLong; 599 599 } 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: " ); 601 601 } // if 602 602 break; … … 966 966 } // if 967 967 } catch( SemanticError &e ) { 968 e.set_location( cur->location );969 968 errors.append( e ); 970 969 } // try … … 1001 1000 } // if 1002 1001 } catch( SemanticError &e ) { 1003 e.set_location( cur->location );1004 1002 errors.append( e ); 1005 1003 } // try … … 1020 1018 * out++ = cur->buildType(); 1021 1019 } catch( SemanticError &e ) { 1022 e.set_location( cur->location );1023 1020 errors.append( e ); 1024 1021 } // try … … 1032 1029 1033 1030 Declaration * 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 " ); 1035 1032 1036 1033 if ( asmStmt ) { … … 1055 1052 // inline _Noreturn int i; // disallowed 1056 1053 if ( type->kind != TypeData::Function && funcSpecs.any() ) { 1057 throw SemanticError( "invalid function specifier for ", this);1054 throw SemanticError( this, "invalid function specifier for " ); 1058 1055 } // if 1059 1056 return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension ); … … 1065 1062 // inlne _Noreturn enum E { ... }; // disallowed 1066 1063 if ( funcSpecs.any() ) { 1067 throw SemanticError( "invalid function specifier for ", this);1064 throw SemanticError( this, "invalid function specifier for " ); 1068 1065 } // if 1069 1066 assertf( name, "ObjectDecl must a have name\n" ); -
src/Parser/ExpressionNode.cc
rc71b256 r7c782af 356 356 357 357 Expression * 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 ); 359 359 Expression * ret = build_constantInteger( *new string( str.substr(1) ) ); 360 360 delete &str; … … 363 363 364 364 Expression * 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 ); 366 366 Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) ); 367 367 delete &str; -
src/Parser/LinkageSpec.cc
rc71b256 r7c782af 24 24 namespace LinkageSpec { 25 25 26 Spec linkageCheck( const string * spec ) {26 Spec linkageCheck( CodeLocation location, const string * spec ) { 27 27 assert( spec ); 28 28 unique_ptr<const string> guard( spec ); // allocated by lexer … … 34 34 return BuiltinC; 35 35 } else { 36 throw SemanticError( "Invalid linkage specifier " + *spec );36 throw SemanticError( location, "Invalid linkage specifier " + *spec ); 37 37 } // if 38 38 } 39 39 40 Spec linkageUpdate( Spec old_spec, const string * cmd ) {40 Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) { 41 41 assert( cmd ); 42 42 unique_ptr<const string> guard( cmd ); // allocated by lexer … … 48 48 return old_spec; 49 49 } else { 50 throw SemanticError( "Invalid linkage specifier " + *cmd );50 throw SemanticError( location, "Invalid linkage specifier " + *cmd ); 51 51 } // if 52 52 } -
src/Parser/LinkageSpec.h
rc71b256 r7c782af 17 17 18 18 #include <string> 19 20 #include "Common/CodeLocation.h" 19 21 20 22 namespace LinkageSpec { … … 45 47 46 48 47 Spec linkageCheck( const std::string * );49 Spec linkageCheck( CodeLocation location, const std::string * ); 48 50 // 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 ); 50 52 /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false 51 53 * If cmd = "Cforall" returns old_spec Spec with is_mangled = true -
src/Parser/ParseNode.h
rc71b256 r7c782af 434 434 } // if 435 435 } catch( SemanticError &e ) { 436 e.set_location( cur->location );437 436 errors.append( e ); 438 437 } // try -
src/Parser/TypeData.cc
rc71b256 r7c782af 31 31 using namespace std; 32 32 33 TypeData::TypeData( Kind k ) : kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {33 TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ { 34 34 switch ( kind ) { 35 35 case Unknown: … … 521 521 522 522 static 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] + "\"." ); 524 524 } // genTSError 525 525 … … 800 800 assert( td->base ); 801 801 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 ); 803 803 } else { 804 804 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); … … 923 923 // type set => parameter name already transformed by a declaration names so there is a duplicate 924 924 // 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 ); 926 926 // declaration type reset => declaration already transformed by a parameter name so there is a duplicate 927 927 // 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 ); 929 929 param->type = decl->type; // set copy declaration type to parameter type 930 930 decl->type = nullptr; // reset declaration type … … 933 933 } // for 934 934 // 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 ); 936 936 } // for 937 937 -
src/Parser/TypeData.h
rc71b256 r7c782af 76 76 }; 77 77 78 CodeLocation location; 79 78 80 Kind kind; 79 81 TypeData * base; -
src/Parser/parser.yy
rc71b256 r7c782af 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 21 11:32:56 201713 // Update Count : 299612 // Last Modified On : Thu Feb 15 17:12:31 2018 13 // Update Count : 3006 14 14 // 15 15 … … 482 482 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); } 483 483 | type_name '.' no_attr_identifier // CFA, nested type 484 { throw SemanticError( "Qualified names are currently unimplemented."); $$ = nullptr; }// FIX ME484 { throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME 485 485 | 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 491 generic_assoc_list: // C11 492 | generic_association 493 | generic_assoc_list ',' generic_association 494 ; 495 496 generic_association: // C11 497 type_no_function ':' assignment_expression 498 | DEFAULT ':' assignment_expression 487 499 ; 488 500 … … 767 779 | unary_expression assignment_operator assignment_expression 768 780 { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); } 781 | unary_expression '=' '{' initializer_list comma_opt '}' // FIX ME 782 { $$ = nullptr; } 769 783 ; 770 784 … … 1050 1064 | RETURN comma_expression_opt ';' 1051 1065 { $$ = new StatementNode( build_return( $2 ) ); } 1066 | RETURN '{' initializer_list comma_opt '}' // FIX ME 1067 { $$ = nullptr; } 1052 1068 | THROW assignment_expression_opt ';' // handles rethrow 1053 1069 { $$ = new StatementNode( build_throw( $2 ) ); } … … 1068 1084 mutex_statement: 1069 1085 MUTEX '(' argument_expression_list ')' statement 1070 { throw SemanticError( "Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME1086 { throw SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } // FIX ME 1071 1087 ; 1072 1088 … … 1289 1305 static_assert: 1290 1306 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1291 { throw SemanticError( "Static assert is currently unimplemented."); $$ = nullptr; } // FIX ME1307 { throw SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; } // FIX ME 1292 1308 1293 1309 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function … … 2377 2393 { 2378 2394 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 2379 linkage = LinkageSpec::linkageUpdate( linkage, $2 );2395 linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 ); 2380 2396 } 2381 2397 '{' external_definition_list_opt '}' -
src/ResolvExpr/AlternativeFinder.cc
rc71b256 r7c782af 239 239 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 240 240 ) 241 throw SemanticError( "No reasonable alternatives for expression ", expr);241 throw SemanticError( expr, "No reasonable alternatives for expression " ); 242 242 } 243 243 if ( prune ) { … … 257 257 stream << "Alternatives are:\n"; 258 258 printAlts( winners, stream, 1 ); 259 throw SemanticError( stream.str() );259 throw SemanticError( expr->location, stream.str() ); 260 260 } 261 261 alternatives = move(pruned); … … 494 494 return; 495 495 } else if ( level >= recursionLimit ) { 496 throw SemanticError( "Too many recursive assertions" );496 throw SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 497 497 } else { 498 498 AssertionSet newerNeed; … … 1408 1408 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1409 1409 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: " ); 1411 1411 } // if 1412 1412 // return the lowest cost alternative for the argument … … 1429 1429 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1430 1430 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: " ); 1432 1432 } // if 1433 1433 // return the lowest cost alternative for the argument -
src/ResolvExpr/CurrentObject.cc
rc71b256 r7c782af 141 141 base = at->get_base(); 142 142 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 @=" ); 144 144 setSize( at->get_dimension() ); 145 145 } … … 156 156 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 157 157 } 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: " ); 159 159 } 160 160 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { … … 179 179 index = constExpr->intValue(); 180 180 } 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: " ); 182 182 } 183 183 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { … … 532 532 } // for 533 533 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: ") ); 535 535 } else if ( desigAlts.size() == 0 ) { 536 throw SemanticError( "No reasonable alternatives for designation: ", designation);536 throw SemanticError( designation, "No reasonable alternatives for designation: " ); 537 537 } 538 538 DesignatorChain & d = desigAlts.back(); -
src/ResolvExpr/Resolver.cc
rc71b256 r7c782af 174 174 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 175 175 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: ") ); 177 177 } else if ( winners.size() != 1 ) { 178 178 std::ostringstream stream; … … 181 181 stream << "Alternatives are:\n"; 182 182 printAlts( winners, stream, 1 ); 183 throw SemanticError( stream.str() );183 throw SemanticError( untyped->location, stream.str() ); 184 184 } 185 185 … … 187 187 Alternative & choice = winners.front(); 188 188 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 " ); 190 190 } 191 191 alt = std::move( choice ); … … 484 484 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 485 485 ss << "' in call to waitfor"; 486 throw SemanticError( s s.str() );486 throw SemanticError( stmt->location, ss.str() ); 487 487 } 488 488 … … 506 506 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 507 507 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" ); 509 509 } 510 510 511 511 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 512 512 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" ); 514 514 } 515 515 … … 520 520 521 521 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"); 523 523 } 524 524 } … … 559 559 // We ran out of parameters but still have arguments 560 560 // 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" ); 562 562 } 563 563 … … 571 571 (*param)->get_type()->print( ss ); 572 572 ss << "'\n"; 573 throw SemanticError( ss.str(), function);573 throw SemanticError( function, ss.str() ); 574 574 } 575 575 … … 583 583 // We ran out of arguments but still have parameters left 584 584 // 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" ); 586 586 } 587 587 … … 610 610 611 611 // 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; } 616 616 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 617 617 -
src/SymTab/Indexer.cc
rc71b256 r7c782af 443 443 // isomorphic to C type-compatibility, which it may not be. 444 444 if ( hasIncompatibleCDecl( name, mangleName, scope ) ) { 445 throw SemanticError( "conflicting overload of C function ", decl);445 throw SemanticError( decl, "conflicting overload of C function " ); 446 446 } 447 447 } else { 448 448 // Check that a Cforall declaration doesn't override any C declaration 449 449 if ( hasCompatibleCDecl( name, mangleName, scope ) ) { 450 throw SemanticError( "Cforall declaration hides C function ", decl);450 throw SemanticError( decl, "Cforall declaration hides C function " ); 451 451 } 452 452 } … … 463 463 void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) { 464 464 // 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 ); 466 466 } 467 467 468 468 void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) { 469 469 // 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 ); 471 471 } 472 472 … … 477 477 return true; 478 478 } else { 479 throw SemanticError( "redeclaration of ", added);479 throw SemanticError( added, "redeclaration of " ); 480 480 } 481 481 } … … 504 504 return false; 505 505 } else if ( ! added->get_members().empty() ) { 506 throw SemanticError( "redeclaration of ", added);506 throw SemanticError( added, "redeclaration of " ); 507 507 } // if 508 508 return true; -
src/SymTab/Validate.cc
rc71b256 r7c782af 361 361 // the only case in which "void" is valid is where it is the only one in the list 362 362 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 " ); 364 364 } 365 365 … … 402 402 for ( Expression * param : inst->parameters ) { 403 403 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: " ); 405 405 } 406 406 } … … 502 502 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name ); 503 503 if ( ! traitDecl ) { 504 throw SemanticError( "use of undeclared trait " + traitInst->name );504 throw SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name ); 505 505 } // if 506 506 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: " ); 508 508 } // if 509 509 traitInst->baseTrait = traitDecl; … … 513 513 TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) ); 514 514 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: " ); 516 516 } 517 517 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) { … … 619 619 bool isVoid = fixFunction( assertion ); 620 620 if ( isVoid ) { 621 throw SemanticError( "invalid type void in assertion of function ", node);621 throw SemanticError( node, "invalid type void in assertion of function " ); 622 622 } // if 623 623 } // for … … 663 663 // were cast to void. 664 664 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: " ); 666 666 } 667 667 } … … 704 704 ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret); 705 705 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 ); 707 707 } 708 708 rtt->get_parameters().clear(); … … 742 742 Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base(); 743 743 if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) { 744 throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );744 throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name ); 745 745 } 746 746 // Cannot redefine VLA typedefs. Note: this is slightly incorrect, because our notion of VLAs … … 749 749 // to fix this corner case likely outweighs the utility of allowing it. 750 750 if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) { 751 throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );751 throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name ); 752 752 } 753 753 } else { … … 847 847 type = new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ); 848 848 } // 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() ) ); 850 850 typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel ); 851 851 } // if … … 898 898 if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc. 899 899 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 " ); 901 901 } 902 902 ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() ); 903 903 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 " ); 905 905 } 906 906 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 " ); 908 908 } 909 909 } … … 940 940 941 941 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 " ); 944 944 } 945 945 } -
src/SynTree/Declaration.h
rc71b256 r7c782af 245 245 typedef NamedTypeDecl Parent; 246 246 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 248 250 TypedefDecl( const TypedefDecl &other ) : Parent( other ) {} 249 251 -
src/SynTree/Expression.cc
rc71b256 r7c782af 93 93 return 0; 94 94 } 95 throw SemanticError( "Constant expression of non-integral type ", this);95 throw SemanticError( this, "Constant expression of non-integral type " ); 96 96 } 97 97 -
src/SynTree/Mutator.h
rc71b256 r7c782af 149 149 } // if 150 150 } catch( SemanticError &e ) { 151 e.set_location( (*i)->location );152 151 errors.append( e ); 153 152 } // try -
src/SynTree/Statement.cc
rc71b256 r7c782af 100 100 //actually this is a syntactic error signaled by the parser 101 101 if ( type == BranchStmt::Goto && target.empty() ) { 102 throw SemanticError( "goto without target");102 throw SemanticError( target.get_statement()->location, "goto without target"); 103 103 } 104 104 } … … 107 107 Statement(), computedTarget( computedTarget ), type( type ) { 108 108 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"); 110 110 } 111 111 } … … 203 203 CaseStmt::CaseStmt( Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) : 204 204 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: " ); 206 206 } 207 207 -
src/SynTree/TypeSubstitution.h
rc71b256 r7c782af 98 98 } // if 99 99 } 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 " ) ); 101 101 } // if 102 102 } else { -
src/SynTree/Visitor.h
rc71b256 r7c782af 143 143 } 144 144 } catch( SemanticError &e ) { 145 e.set_location( (*i)->location );146 145 errors.append( e ); 147 146 } -
src/libcfa/concurrency/alarm.c
rc71b256 r7c782af 18 18 #include <stdio.h> 19 19 #include <string.h> 20 #include <time.h>21 20 #include <unistd.h> 22 21 #include <sys/time.h> … … 27 26 #include "preemption.h" 28 27 29 //=============================================================================================30 // time type31 //=============================================================================================32 28 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 29 static inline void ?{}( itimerval & this, __cfa_time_t * alarm ) with( this ) { 30 it_value.tv_sec = alarm->val / (1`cfa_s).val; // seconds 31 it_value.tv_usec = max( (alarm->val % (1`cfa_s).val) / (1`cfa_us).val, 1000 ); // microseconds 46 32 it_interval.tv_sec = 0; 47 33 it_interval.tv_usec = 0; 48 34 } 49 35 50 51 void ?{}( __cfa_time_t & this, timespec * curr ) { 36 static inline void ?{}( __cfa_time_t & this, timespec * curr ) { 52 37 uint64_t secs = curr->tv_sec; 53 38 uint64_t nsecs = curr->tv_nsec; 54 this.val = (secs * one_second)+ nsecs;39 this.val = from_s(secs).val + nsecs; 55 40 } 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; }66 41 67 42 //============================================================================================= … … 84 59 //============================================================================================= 85 60 86 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time) with( this ) {61 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) { 87 62 this.thrd = thrd; 88 63 this.alarm = alarm; … … 93 68 } 94 69 95 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time) with( this ) {70 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ) with( this ) { 96 71 this.proc = proc; 97 72 this.alarm = alarm; -
src/libcfa/concurrency/alarm.h
rc71b256 r7c782af 21 21 #include <assert.h> 22 22 23 #include "bits/cfatime.h" 24 23 25 struct thread_desc; 24 26 struct processor; 25 26 struct timespec;27 struct itimerval;28 29 //=============================================================================================30 // time type31 //=============================================================================================32 33 struct __cfa_time_t {34 uint64_t val;35 };36 37 // ctors38 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 ops46 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/substract61 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;79 27 80 28 //============================================================================================= … … 105 53 typedef alarm_node_t ** __alarm_it_t; 106 54 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);55 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ); 56 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s ); 109 57 void ^?{}( alarm_node_t & this ); 110 58 -
src/libcfa/concurrency/coroutine.c
rc71b256 r7c782af 99 99 // Wrapper for co 100 100 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 101 verify( preemption.enabled || this_processor->do_terminate ); 101 102 disable_interrupts(); 102 103 … … 116 117 117 118 enable_interrupts( __cfaabi_dbg_ctx ); 119 verify( preemption.enabled || this_processor->do_terminate ); 118 120 } //ctxSwitchDirect 119 121 -
src/libcfa/concurrency/invoke.c
rc71b256 r7c782af 28 28 extern void __suspend_internal(void); 29 29 extern void __leave_coroutine(void); 30 extern void __finish_creation(void); 30 31 extern void __leave_thread_monitor( struct thread_desc * this ); 31 32 extern void disable_interrupts(); … … 44 45 45 46 cor->state = Active; 47 48 enable_interrupts( __cfaabi_dbg_ctx ); 46 49 47 50 main( this ); … … 62 65 // First suspend, once the thread arrives here, 63 66 // the function pointer to main can be invalidated without risk 64 __ suspend_internal();67 __finish_creation(); 65 68 66 69 // Fetch the thread handle from the user defined thread structure -
src/libcfa/concurrency/kernel.c
rc71b256 r7c782af 56 56 thread_local processor * volatile this_processor; 57 57 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 62 volatile thread_local __cfa_kernel_preemption_data_t preemption = { false, false, 1 }; 61 63 62 64 //----------------------------------------------------------------------------- … … 207 209 if(readyThread) 208 210 { 209 verify( !preemption _enabled );211 verify( !preemption.enabled ); 210 212 211 213 runThread(this, readyThread); 212 214 213 verify( !preemption _enabled );215 verify( !preemption.enabled ); 214 216 215 217 //Some actions need to be taken from the kernel … … 260 262 void finishRunning(processor * this) with( this->finish ) { 261 263 if( action_code == Release ) { 262 verify( !preemption _enabled );264 verify( !preemption.enabled ); 263 265 unlock( *lock ); 264 266 } … … 267 269 } 268 270 else if( action_code == Release_Schedule ) { 269 verify( !preemption _enabled );271 verify( !preemption.enabled ); 270 272 unlock( *lock ); 271 273 ScheduleThread( thrd ); 272 274 } 273 275 else if( action_code == Release_Multi ) { 274 verify( !preemption _enabled );276 verify( !preemption.enabled ); 275 277 for(int i = 0; i < lock_count; i++) { 276 278 unlock( *locks[i] ); … … 304 306 this_coroutine = NULL; 305 307 this_thread = NULL; 306 preemption _enabled = false;307 disable_preempt_count = 1;308 preemption.enabled = false; 309 preemption.disable_count = 1; 308 310 // SKULLDUGGERY: We want to create a context for the processor coroutine 309 311 // which is needed for the 2-step context switch. However, there is no reason … … 345 347 } 346 348 349 void kernel_first_resume(processor * this) { 350 coroutine_desc * src = this_coroutine; 351 coroutine_desc * dst = get_coroutine(*this->runner); 352 353 verify( !preemption.enabled ); 354 355 create_stack(&dst->stack, dst->stack.size); 356 CtxStart(this->runner, CtxInvokeCoroutine); 357 358 verify( !preemption.enabled ); 359 360 dst->last = src; 361 dst->starter = dst->starter ? dst->starter : src; 362 363 // set state of current coroutine to inactive 364 src->state = src->state == Halted ? Halted : Inactive; 365 366 // set new coroutine that task is executing 367 this_coroutine = dst; 368 369 // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch. 370 // Therefore, when first creating a coroutine, interrupts are enable before calling the main. 371 // This is consistent with thread creation. However, when creating the main processor coroutine, 372 // we wan't interrupts to be disabled. Therefore, we double-disable interrupts here so they will 373 // stay disabled. 374 disable_interrupts(); 375 376 // context switch to specified coroutine 377 assert( src->stack.context ); 378 CtxSwitch( src->stack.context, dst->stack.context ); 379 // when CtxSwitch returns we are back in the src coroutine 380 381 // set state of new coroutine to active 382 src->state = Active; 383 384 verify( !preemption.enabled ); 385 } 386 347 387 //----------------------------------------------------------------------------- 348 388 // Scheduler routines … … 352 392 verify( thrd->self_cor.state != Halted ); 353 393 354 verify( !preemption _enabled );394 verify( !preemption.enabled ); 355 395 356 396 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); … … 362 402 } 363 403 364 verify( !preemption _enabled );404 verify( !preemption.enabled ); 365 405 } 366 406 367 407 thread_desc * nextThread(cluster * this) with( *this ) { 368 verify( !preemption _enabled );408 verify( !preemption.enabled ); 369 409 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 370 410 thread_desc * head = pop_head( ready_queue ); 371 411 unlock( ready_queue_lock ); 372 verify( !preemption _enabled );412 verify( !preemption.enabled ); 373 413 return head; 374 414 } … … 376 416 void BlockInternal() { 377 417 disable_interrupts(); 378 verify( !preemption _enabled );418 verify( !preemption.enabled ); 379 419 returnToKernel(); 380 verify( !preemption _enabled );420 verify( !preemption.enabled ); 381 421 enable_interrupts( __cfaabi_dbg_ctx ); 382 422 } … … 387 427 this_processor->finish.lock = lock; 388 428 389 verify( !preemption _enabled );429 verify( !preemption.enabled ); 390 430 returnToKernel(); 391 verify( !preemption _enabled );431 verify( !preemption.enabled ); 392 432 393 433 enable_interrupts( __cfaabi_dbg_ctx ); … … 399 439 this_processor->finish.thrd = thrd; 400 440 401 verify( !preemption _enabled );441 verify( !preemption.enabled ); 402 442 returnToKernel(); 403 verify( !preemption _enabled );443 verify( !preemption.enabled ); 404 444 405 445 enable_interrupts( __cfaabi_dbg_ctx ); … … 413 453 this_processor->finish.thrd = thrd; 414 454 415 verify( !preemption _enabled );455 verify( !preemption.enabled ); 416 456 returnToKernel(); 417 verify( !preemption _enabled );457 verify( !preemption.enabled ); 418 458 419 459 enable_interrupts( __cfaabi_dbg_ctx ); … … 426 466 this_processor->finish.lock_count = count; 427 467 428 verify( !preemption _enabled );468 verify( !preemption.enabled ); 429 469 returnToKernel(); 430 verify( !preemption _enabled );470 verify( !preemption.enabled ); 431 471 432 472 enable_interrupts( __cfaabi_dbg_ctx ); … … 441 481 this_processor->finish.thrd_count = thrd_count; 442 482 443 verify( !preemption _enabled );483 verify( !preemption.enabled ); 444 484 returnToKernel(); 445 verify( !preemption _enabled );485 verify( !preemption.enabled ); 446 486 447 487 enable_interrupts( __cfaabi_dbg_ctx ); … … 449 489 450 490 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 451 verify( !preemption _enabled );491 verify( !preemption.enabled ); 452 492 this_processor->finish.action_code = thrd ? Release_Schedule : Release; 453 493 this_processor->finish.lock = lock; … … 463 503 // Kernel boot procedures 464 504 void kernel_startup(void) { 505 verify( !preemption.enabled ); 465 506 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 466 507 … … 500 541 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 501 542 // mainThread is on the ready queue when this call is made. 502 resume( *mainProcessor->runner );543 kernel_first_resume( this_processor ); 503 544 504 545 … … 507 548 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 508 549 550 verify( !preemption.enabled ); 509 551 enable_interrupts( __cfaabi_dbg_ctx ); 552 verify( preemption.enabled ); 510 553 } 511 554 … … 513 556 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 514 557 558 verify( preemption.enabled ); 515 559 disable_interrupts(); 560 verify( !preemption.enabled ); 516 561 517 562 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. -
src/libcfa/concurrency/kernel_private.h
rc71b256 r7c782af 74 74 extern thread_local processor * volatile this_processor; 75 75 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 80 struct __cfa_kernel_preemption_data_t { 81 bool enabled; 82 bool in_progress; 83 unsigned short disable_count; 84 }; 85 86 extern volatile thread_local __cfa_kernel_preemption_data_t preemption; 79 87 80 88 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/monitor.c
rc71b256 r7c782af 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 8 16:12:20201813 // Update Count : 412 // Last Modified On : Fri Feb 16 14:49:53 2018 13 // Update Count : 5 14 14 // 15 15 … … 427 427 thread_desc * this_thrd = this_thread; 428 428 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 ); 430 430 } 431 431 -
src/libcfa/concurrency/preemption.c
rc71b256 r7c782af 149 149 // Disable interrupts by incrementing the counter 150 150 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; 154 154 verify( new_val < 65_000u ); // If this triggers someone is disabling interrupts without enabling them 155 155 } … … 161 161 thread_desc * thrd = this_thread; // Cache the thread now since interrupts can start happening after the atomic add 162 162 163 unsigned short prev = disable_preempt_count;164 disable_preempt_count -= 1;163 unsigned short prev = preemption.disable_count; 164 preemption.disable_count -= 1; 165 165 verify( prev != 0u ); // If this triggers someone is enabled already enabled interruptsverify( prev != 0u ); 166 166 167 167 // Check if we need to prempt the thread because an interrupt was missed 168 168 if( prev == 1 ) { 169 preemption _enabled = true;169 preemption.enabled = true; 170 170 if( proc->pending_preemption ) { 171 171 proc->pending_preemption = false; … … 181 181 // Don't execute any pending CtxSwitch even if counter reaches 0 182 182 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; 185 185 verifyf( prev != 0u, "Incremented from %u\n", prev ); // If this triggers someone is enabled already enabled interrupts 186 186 if( prev == 1 ) { 187 preemption _enabled = true;187 preemption.enabled = true; 188 188 } 189 189 } … … 235 235 // If false : preemption is unsafe and marked as pending 236 236 static inline bool preemption_ready() { 237 bool ready = preemption _enabled && !preemption_in_progress; // Check if preemption is safe237 bool ready = preemption.enabled && !preemption.in_progress; // Check if preemption is safe 238 238 this_processor->pending_preemption = !ready; // Adjust the pending flag accordingly 239 239 return ready; … … 250 250 251 251 // Start with preemption disabled until ready 252 preemption _enabled = false;253 disable_preempt_count = 1;252 preemption.enabled = false; 253 preemption.disable_count = 1; 254 254 255 255 // Initialize the event kernel … … 290 290 // Used by thread to control when they want to receive preemption signals 291 291 void ?{}( preemption_scope & this, processor * proc ) { 292 (this.alarm){ proc, zero_time, zero_time};292 (this.alarm){ proc, 0`cfa_s, 0`cfa_s }; 293 293 this.proc = proc; 294 294 this.proc->preemption_alarm = &this.alarm; … … 300 300 disable_interrupts(); 301 301 302 update_preemption( this.proc, zero_time);302 update_preemption( this.proc, 0`cfa_s ); 303 303 } 304 304 … … 330 330 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread); 331 331 332 preemption _in_progress = true; // Sync flag : prevent recursive calls to the signal handler332 preemption.in_progress = true; // Sync flag : prevent recursive calls to the signal handler 333 333 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 flag334 preemption.in_progress = false; // Clear the in progress flag 335 335 336 336 // Preemption can occur here -
src/libcfa/concurrency/thread.c
rc71b256 r7c782af 90 90 } 91 91 92 extern "C" { 93 void __finish_creation(void) { 94 coroutine_desc* thrd_c = this_coroutine; 95 ThreadCtxSwitch( thrd_c, thrd_c->last ); 96 } 97 } 98 92 99 void yield( void ) { 100 verify( preemption.enabled ); 93 101 BlockInternal( this_thread ); 102 verify( preemption.enabled ); 94 103 } 95 104 -
src/main.cc
rc71b256 r7c782af 282 282 } // if 283 283 284 CodeTools::fillLocations( translationUnit ); 285 284 286 OPTPRINT( "resolve" ) 285 287 ResolvExpr::resolve( translationUnit ); … … 361 363 cerr << endl << "---End of AST, begin error message:---\n" << endl; 362 364 } // if 363 e.print( cerr);365 e.print(); 364 366 if ( output != &cout ) { 365 367 delete output; -
src/tests/.expect/alloc.txt
rc71b256 r7c782af 2 2 CFA malloc 0xdeadbeef 3 3 CFA alloc 0xdeadbeef 4 CFA alloc, fill 010101014 CFA alloc, fill ffffffff 5 5 6 6 C array calloc, fill 0 … … 10 10 CFA array alloc, no fill 11 11 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 12 CFA array alloc, fill 0x 113 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x101010112 CFA array alloc, fill 0xff 13 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 14 14 15 15 C realloc … … 25 25 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 26 26 CFA resize array alloc, fill 27 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x101010127 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 28 28 CFA resize array alloc, fill 29 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x101010129 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 30 30 CFA resize array alloc, fill 31 0x 1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x101010131 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 32 32 33 33 C memalign 42 42.5 … … 37 37 CFA aligned_alloc 42 42.5 38 38 CFA align_alloc 42 42.5 39 CFA align_alloc fill 0x 1010101 0x1.1010101010101p-100739 CFA align_alloc fill 0xffffffff -nan 40 40 41 41 CFA array align_alloc 42 42 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, 42 42.5, 43 43 CFA array align_alloc, fill 44 0x 1010101 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,44 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 45 45 46 CFA memset 0x 1010101 0x1.1010101010101p-100747 CFA memcpy 0x 1010101 0x1.1010101010101p-100746 CFA memset 0xffffffff -nan 47 CFA memcpy 0xffffffff -nan 48 48 49 49 CFA array memset 50 0x 1010101 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,50 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 51 51 CFA memcpy 52 0x 1010101 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,52 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 53 53 54 54 CFA new initialize -
src/tests/alloc.c
rc71b256 r7c782af 10 10 // Created On : Wed Feb 3 07:56:22 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 22 21:26:40201813 // Update Count : 3 2612 // Last Modified On : Fri Feb 16 15:42:31 2018 13 // Update Count : 330 14 14 // 15 15 … … 27 27 int main( void ) { 28 28 size_t dim = 10; 29 char fill = '\xff'; 29 30 int * p; 30 char fill = '\1';31 31 32 32 // allocation, non-array types … … 79 79 80 80 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 ); 82 82 for ( int i = 0; i < 2 * dim; i += 1 ) { printf( "%#x ", p[i] ); } 83 83 printf( "\n" ); -
src/tests/raii/.expect/dtor-early-exit-ERR2.txt
rc71b256 r7c782af 1 raii/dtor-early-exit.c:2 20:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)1 raii/dtor-early-exit.c:217:1 error: jump to label 'L2' crosses initialization of y Branch (Goto) 2 2 with target: L2 3 3 with original target: L2
Note:
See TracChangeset
for help on using the changeset viewer.