Changes in / [7c782af:c71b256]
- Files:
-
- 1 deleted
- 49 edited
-
doc/LaTeXmacros/common.tex (modified) (3 diffs)
-
doc/papers/general/Paper.tex (modified) (31 diffs)
-
doc/user/user.tex (modified) (62 diffs)
-
src/CodeGen/FixMain.cc (modified) (1 diff)
-
src/CodeGen/FixNames.cc (modified) (1 diff)
-
src/Common/PassVisitor.impl.h (modified) (5 diffs)
-
src/Common/SemanticError.cc (modified) (3 diffs)
-
src/Common/SemanticError.h (modified) (3 diffs)
-
src/Concurrency/Keywords.cc (modified) (6 diffs)
-
src/Concurrency/Waitfor.cc (modified) (1 diff)
-
src/ControlStruct/ExceptTranslate.cc (modified) (1 diff)
-
src/ControlStruct/LabelFixer.cc (modified) (2 diffs)
-
src/ControlStruct/MLEMutator.cc (modified) (2 diffs)
-
src/GenPoly/Box.cc (modified) (3 diffs)
-
src/InitTweak/FixInit.cc (modified) (3 diffs)
-
src/InitTweak/GenInit.cc (modified) (1 diff)
-
src/InitTweak/InitTweak.cc (modified) (1 diff)
-
src/Parser/DeclarationNode.cc (modified) (8 diffs)
-
src/Parser/ExpressionNode.cc (modified) (2 diffs)
-
src/Parser/LinkageSpec.cc (modified) (3 diffs)
-
src/Parser/LinkageSpec.h (modified) (2 diffs)
-
src/Parser/ParseNode.h (modified) (1 diff)
-
src/Parser/TypeData.cc (modified) (5 diffs)
-
src/Parser/TypeData.h (modified) (1 diff)
-
src/Parser/parser.yy (modified) (7 diffs)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (5 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (4 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (10 diffs)
-
src/SymTab/Indexer.cc (modified) (4 diffs)
-
src/SymTab/Validate.cc (modified) (12 diffs)
-
src/SynTree/Declaration.h (modified) (1 diff)
-
src/SynTree/Expression.cc (modified) (1 diff)
-
src/SynTree/Mutator.h (modified) (1 diff)
-
src/SynTree/Statement.cc (modified) (3 diffs)
-
src/SynTree/TypeSubstitution.h (modified) (1 diff)
-
src/SynTree/Visitor.h (modified) (1 diff)
-
src/libcfa/bits/cfatime.h (deleted)
-
src/libcfa/concurrency/alarm.c (modified) (4 diffs)
-
src/libcfa/concurrency/alarm.h (modified) (2 diffs)
-
src/libcfa/concurrency/coroutine.c (modified) (2 diffs)
-
src/libcfa/concurrency/invoke.c (modified) (3 diffs)
-
src/libcfa/concurrency/kernel.c (modified) (19 diffs)
-
src/libcfa/concurrency/kernel_private.h (modified) (1 diff)
-
src/libcfa/concurrency/monitor.c (modified) (2 diffs)
-
src/libcfa/concurrency/preemption.c (modified) (8 diffs)
-
src/libcfa/concurrency/thread.c (modified) (1 diff)
-
src/main.cc (modified) (2 diffs)
-
src/tests/.expect/alloc.txt (modified) (4 diffs)
-
src/tests/alloc.c (modified) (3 diffs)
-
src/tests/raii/.expect/dtor-early-exit-ERR2.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
r7c782af rc71b256 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Feb 13 08:19:07201814 %% Update Count : 36 713 %% Last Modified On : Sun Feb 4 10:38:26 2018 14 %% Update Count : 365 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 177 177 \makeatother 178 178 179 \newenvironment{ cquote}{%180 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent lnth\rightmargin\leftmargin}%179 \newenvironment{quote2}{% 180 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}% 181 181 \item\relax 182 182 }{% 183 183 \endlist 184 }% cquote184 }% quote2 185 185 186 186 \newenvironment{rationale}{% 187 \begin{ cquote}\noindent$\Box$\enspace187 \begin{quote2}\noindent$\Box$\enspace 188 188 }{% 189 \hfill\enspace$\Box$\end{ cquote}189 \hfill\enspace$\Box$\end{quote2} 190 190 }% 191 191 … … 201 201 \newenvironment{syntax}{ 202 202 \paragraph{Syntax} 203 \begin{ cquote}203 \begin{quote2} 204 204 \begin{description}[noitemsep,leftmargin=\parindentlnth] 205 205 }{ 206 206 \end{description} 207 \end{ cquote}207 \end{quote2} 208 208 } 209 209 % \def\syntax{\paragraph{Syntax}\trivlist\parindent=.5in\item[\hskip.5in]} -
doc/papers/general/Paper.tex
r7c782af rc71b256 4 4 \usepackage{epic,eepic} 5 5 \usepackage{xspace,calc,comment} 6 \usepackage{upquote} % switch curled `'" to straight 7 \usepackage{listings} % format program code 8 \usepackage{enumitem} 9 \usepackage[flushmargin]{footmisc} % support label/reference in footnote 6 \usepackage{upquote} % switch curled `'" to straight 7 \usepackage{listings} % format program code 10 8 \usepackage{rotating} 11 9 \usepackage[usenames]{color} 12 \usepackage{pslatex} % reduce size of san serif font10 \usepackage{pslatex} % reduce size of san serif font 13 11 \usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref} 14 12 15 13 \setlength{\textheight}{9in} 16 14 %\oddsidemargin 0.0in 17 \renewcommand{\topfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page18 \renewcommand{\bottomfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page19 \renewcommand{\floatpagefraction}{0.8} % float must be greater than X of the page before it is forced onto its own page20 \renewcommand{\textfraction}{0.0} % the entire page maybe devoted to floats with no text on the page at all21 22 \lefthyphenmin=4 % hyphen only after 4 characters15 \renewcommand{\topfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page 16 \renewcommand{\bottomfraction}{0.8} % float must be greater than X of the page before it is forced onto its own page 17 \renewcommand{\floatpagefraction}{0.8} % float must be greater than X of the page before it is forced onto its own page 18 \renewcommand{\textfraction}{0.0} % the entire page maybe devoted to floats with no text on the page at all 19 20 \lefthyphenmin=4 % hyphen only after 4 characters 23 21 \righthyphenmin=4 24 22 … … 26 24 27 25 \newcommand{\CFAIcon}{\textsf{C}\raisebox{\depth}{\rotatebox{180}{\textsf{A}}}\xspace} % Cforall symbolic name 28 \newcommand{\CFA}{\protect\CFAIcon} % safe for section/caption29 \newcommand{\CFL}{\textrm{Cforall}\xspace} % Cforall symbolic name30 \newcommand{\Celeven}{\textrm{C11}\xspace} % C11 symbolic name26 \newcommand{\CFA}{\protect\CFAIcon} % safe for section/caption 27 \newcommand{\CFL}{\textrm{Cforall}\xspace} % Cforall symbolic name 28 \newcommand{\Celeven}{\textrm{C11}\xspace} % C11 symbolic name 31 29 \newcommand{\CC}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}\xspace} % C++ symbolic name 32 30 \newcommand{\CCeleven}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name … … 58 56 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 59 57 60 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly58 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly 61 59 \newlength{\columnposn} 62 60 \setlength{\gcolumnposn}{2.75in} … … 74 72 75 73 % Latin abbreviation 76 \newcommand{\abbrevFont}{\textit} % set empty for no italics74 \newcommand{\abbrevFont}{\textit} % set empty for no italics 77 75 \newcommand{\EG}{\abbrevFont{e}.\abbrevFont{g}.} 78 76 \newcommand*{\eg}{% … … 105 103 106 104 \newenvironment{cquote}{% 107 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent lnth\rightmargin\leftmargin}%105 \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}% 108 106 \item\relax 109 107 }{% … … 189 187 190 188 191 \section{Introduction }189 \section{Introduction and Background} 192 190 193 191 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. … … 195 193 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. 196 194 The top 3 rankings over the past 30 years are: 195 \lstDeleteShortInline@% 197 196 \begin{center} 198 197 \setlength{\tabcolsep}{10pt} 199 \lstDeleteShortInline@%200 198 \begin{tabular}{@{}rccccccc@{}} 201 199 & 2017 & 2012 & 2007 & 2002 & 1997 & 1992 & 1987 \\ \hline … … 204 202 \CC & 3 & 3 & 3 & 3 & 2 & 2 & 4 \\ 205 203 \end{tabular} 204 \end{center} 206 205 \lstMakeShortInline@% 207 \end{center}208 206 Love it or hate it, C is extremely popular, highly used, and one of the few systems languages. 209 207 In many cases, \CC is often used solely as a better C. … … 226 224 The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance. 227 225 228 \section{Polymorphic Functions} 229 230 \CFA introduces both ad-hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}. 231 232 \subsection{Name Overloading} 233 234 C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax. 235 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C. 236 Code generation for these overloaded functions and variables is implemented by the usual approach of mangling the identifier names to include a representation of their type, while \CFA decides which overload to apply based on the same ``usual arithmetic conversions'' used in C to disambiguate operator overloads. 237 As an example: 238 239 \begin{cfa} 240 int max(int a, int b) { return a < b ? b : a; } // (1) 241 double max(double a, double b) { return a < b ? b : a; } // (2) 242 243 int max = INT_MAX; // (3) 244 double max = DBL_MAX; // (4) 245 246 max(7, -max); $\C{// uses (1) and (3), by matching int from constant 7}$ 247 max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$ 248 249 //max(max, -max); $\C{// ERROR: ambiguous}$ 250 int m = max(max, -max); $\C{// uses (1) once and (3) twice, by matching return type}$ 251 \end{cfa} 252 253 \Celeven did add @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 254 The macro wrapping the generic expression imposes some limitations; as an example, it could not implement the example above, because the variables @max@ would collide with the functions @max@. 255 Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the functions dispatched to, which must all have distinct names. 256 257 \subsection{\texorpdfstring{\LstKeywordStyle{forall} Functions}{forall Functions}} 226 227 \subsection{Polymorphic Functions} 258 228 \label{sec:poly-fns} 259 229 230 \CFA{}\hspace{1pt}'s polymorphism was originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}. 260 231 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): 261 232 \begin{lstlisting} … … 286 257 Crucial to the design of a new programming language are the libraries to access thousands of external software features. 287 258 Like \CC, \CFA inherits a massive compatible library-base, where other programming languages must rewrite or provide fragile inter-language communication with C. 288 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:259 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted floating-point array: 289 260 \begin{lstlisting} 290 261 void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, … … 292 263 int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 : 293 264 *(double *)t2 < *(double *)t1 ? 1 : 0; } 294 double key = 5.0, vals[10] = { /* 10 sorted float values */ };265 double key = 5.0, vals[10] = { /* 10 sorted floating-point values */ }; 295 266 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ 296 267 \end{lstlisting} … … 333 304 Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types. 334 305 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@. 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@. 343 312 344 313 \subsection{Traits} … … 536 505 In many languages, functions can return at most one value; 537 506 however, many operations have multiple outcomes, some exceptional. 538 Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively.507 Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and floating-point values, respectively. 539 508 \begin{lstlisting} 540 509 typedef struct { int quo, rem; } div_t; $\C{// from include stdlib.h}$ … … 967 936 968 937 \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.971 938 972 939 … … 1077 1044 The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed. 1078 1045 1079 1080 1046 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}} 1081 1047 1082 There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses. 1083 1084 C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}. 1085 \CFA provides a shorthand for a non-contiguous list: 1086 \begin{cquote} 1087 \lstDeleteShortInline@% 1088 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1089 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1090 \begin{cfa} 1091 case 2, 10, 34, 42: 1092 \end{cfa} 1093 & 1094 \begin{cfa} 1095 case 2: case 10: case 34: case 42: 1096 \end{cfa} 1097 \end{tabular} 1098 \lstMakeShortInline@% 1099 \end{cquote} 1100 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1101 \begin{cquote} 1102 \lstDeleteShortInline@% 1103 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1104 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1105 \begin{cfa} 1106 case 2~42: 1107 \end{cfa} 1108 & 1109 \begin{cfa} 1110 case 2: case 3: ... case 41: case 42: 1111 \end{cfa} 1112 \end{tabular} 1113 \lstMakeShortInline@% 1114 \end{cquote} 1115 and a combination: 1116 \begin{cfa} 1117 case -12~-4, -1~5, 14~21, 34~42: 1118 \end{cfa} 1119 1120 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1121 \begin{cfa} 1122 switch ( i ) { 1123 case 0: 1124 for ( int i = 0; i < 10; i += 1 ) { 1125 ... 1126 `case 1:` // no initialization of loop index 1127 ... 1128 } 1129 } 1130 \end{cfa} 1131 \CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality. 1132 1133 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1134 \begin{cfa} 1135 switch ( x ) { 1136 `int y = 1;` $\C{// unreachable initialization}$ 1137 `x = 7;` $\C{// unreachable code without label/branch}$ 1138 case 0: 1139 ... 1140 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1141 z = 2; 1142 case 1: 1143 `x = z;` $\C{// without fall through, z is undefined}$ 1144 } 1145 \end{cfa} 1146 \CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses, but no statements. 1147 \CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred. 1148 1149 C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through}; 1150 @case@ clauses are made disjoint by the @break@ statement. 1151 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements. 1152 \CFA provides a new control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through: 1153 \begin{cquote} 1154 \lstDeleteShortInline@% 1155 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1156 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1157 \begin{cfa} 1158 `choose` ( day ) { 1159 case Mon~Thu: 1160 // program 1161 1162 case Fri: 1163 // program 1164 wallet += pay; 1165 `fallthrough;` 1166 case Sat: 1167 // party 1168 wallet -= party; 1169 1170 case Sun: 1171 // rest 1172 1173 default: 1174 // error 1175 } 1176 \end{cfa} 1177 & 1178 \begin{cfa} 1179 switch ( day ) { 1180 case Mon: case Tue: case Wed: case Thu: 1181 // program 1182 `break;` 1183 case Fri: 1184 // program 1185 wallet += pay; 1186 1187 case Sat: 1188 // party 1189 wallet -= party; 1190 `break;` 1191 case Sun: 1192 // rest 1193 `break;` 1194 default: 1195 // error 1196 } 1197 \end{cfa} 1198 \end{tabular} 1199 \lstMakeShortInline@% 1200 \end{cquote} 1201 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1202 1203 \begin{comment} 1048 \CFA also fixes a number of ergonomic defecits in the @switch@ statements of standard C. 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 1204 1052 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. 1205 1053 \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. … … 1222 1070 } 1223 1071 \end{cfa} 1224 \end{comment}1225 1226 1072 1227 1073 \subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}} … … 1360 1206 \end{cfa} 1361 1207 1362 % \subsection{Exception Handling ???} 1208 1209 \subsection{Exception Handling ???} 1210 1363 1211 1364 1212 \section{Declarations} … … 1407 1255 \lstDeleteShortInline@% 1408 1256 \lstset{moredelim=**[is][\color{blue}]{+}{+}} 1409 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{}}1410 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1257 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1258 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1411 1259 \begin{cfa} 1412 1260 +[5] *+ `int` x1; 1413 1261 +* [5]+ `int` x2; 1414 `[* [5] int]` f+( int p )+;1262 +[* [5] int]+ f`( int p )`; 1415 1263 \end{cfa} 1416 1264 & … … 1418 1266 `int` +*+ x1 +[5]+; 1419 1267 `int` +(*+x2+)[5]+; 1420 `int (*`f+( int p )+`)[5]`;1268 +int (*+f`( int p )`+)[5]+; 1421 1269 \end{cfa} 1422 1270 \end{tabular} … … 1429 1277 \begin{cquote} 1430 1278 \lstDeleteShortInline@% 1431 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{}}1432 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1279 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1280 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1433 1281 \begin{cfa} 1434 1282 `*` int x, y; … … 1444 1292 \begin{cquote} 1445 1293 \lstDeleteShortInline@% 1446 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{}}1447 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1294 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1295 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1448 1296 \begin{cfa} 1449 1297 `*` int x; … … 1462 1310 \begin{cquote} 1463 1311 \lstDeleteShortInline@% 1464 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}1465 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}} \\1312 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1313 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ 1466 1314 \begin{cfa} 1467 1315 [ 5 ] int z; … … 1503 1351 \begin{cquote} 1504 1352 \lstDeleteShortInline@% 1505 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}1506 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}} \\1353 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 1354 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\ 1507 1355 \begin{cfa} 1508 1356 const * const int x; … … 1526 1374 \begin{cquote} 1527 1375 \lstDeleteShortInline@% 1528 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}1529 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{C}} \\1376 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1377 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ 1530 1378 \begin{cfa} 1531 1379 extern [ 5 ] int x; … … 1549 1397 \begin{cquote} 1550 1398 \lstDeleteShortInline@% 1551 \begin{tabular}{@{}l@{\hspace{ \parindentlnth}}l@{}}1552 \multicolumn{1}{c@{\hspace{ \parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\1399 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1400 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1553 1401 \begin{cfa} 1554 1402 y = (* int)x; … … 1567 1415 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style. 1568 1416 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}1614 1417 1615 1418 … … 1790 1593 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. 1791 1594 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 \centering1798 \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 \hline1802 \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 qualification1853 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 1867 1595 \subsection{Default Parameters} 1868 1596 … … 1870 1598 \section{Literals} 1871 1599 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.1600 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and floating-point types are very similar, differing from each other only in suffix. 1873 1601 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. 1874 1602 … … 1894 1622 struct Weight { double stones; }; 1895 1623 1896 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$1624 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$ 1897 1625 void ?{}( Weight & w, double w ) { w.stones = w; } 1898 1626 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } … … 1903 1631 1904 1632 int main() { 1905 Weight w, hw = { 14 }; $\C{// 14 stone}$1633 Weight w, hw = { 14 }; $\C{// 14 stone}$ 1906 1634 w = 11@`st@ + 1@`lb@; 1907 1635 w = 70.3@`kg@; 1908 1636 w = 155@`lb@; 1909 w = 0x_9b_u@`lb@; $\C{// hexadecimal unsigned weight (155)}$1910 w = 0_233@`lb@; $\C{// octal weight (155)}$1637 w = 0x_9b_u@`lb@; $\C{// hexadecimal unsigned weight (155)}$ 1638 w = 0_233@`lb@; $\C{// octal weight (155)}$ 1911 1639 w = 5@`st@ + 8@`kg@ + 25@`lb@ + hw; 1912 1640 } 1913 1641 \end{cfa} 1914 1642 }% 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 MIN1956 MAX1957 M_PI1958 M_E1959 \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_CEl1966 \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 log2001 sqrt2002 sin2003 \end{cfa}2004 &2005 \begin{cfa}2006 logf, log, logl, clogf, clog, clogl2007 sqrtf, sqrt, sqrtl, csqrtf, csqrt, csqrtl2008 sinf, sin, sinl, csinf, csin, csinl2009 \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 abs2048 strto2049 random2050 \end{cfa}2051 &2052 \begin{cfa}2053 abs, labs, llabs, fabsf, fabs, fabsl, cabsf, cabs, cabsl2054 strtol, strtoul, strtoll, strtoull, strtof, strtod, strtold2055 srand48, mrand48, lrand48, drand482056 \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 \centering2135 \lstDeleteShortInline@%2136 \lstMakeShortInline~%2137 \begin{tabular}{@{}r|r|l|l|l|l@{}}2138 \multicolumn{1}{c}{}& & \multicolumn{1}{c|}{fill} & resize & alignment & array \\2139 \hline2140 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 \hline2146 C11 & ~aligned_alloc~ & no & no & yes & no \\2147 \hline2148 \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` `32182 \end{cfa}2183 &2184 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]2185 1 2 32186 \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`, `62198 \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 22220 \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 \item2230 A separator does not appear at the start or end of a line.2231 \item2232 A separator does not appear before or after a character literal or variable.2233 \item2234 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 \item2236 A separator does not appear before a C string starting with the characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$@2237 \item2238 A seperator does not appear after a C string ending with the characters: \lstinline[basicstyle=\tt]@,.;!?)]}%@2239 \item2240 {\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 \item2244 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 2290 1643 2291 1644 \section{Evaluation} … … 2351 1704 2352 1705 \begin{table} 2353 \centering2354 1706 \caption{Properties of benchmark code} 2355 1707 \label{tab:eval} -
doc/user/user.tex
r7c782af rc71b256 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Feb 13 08:31:21201814 %% Update Count : 31 6113 %% Last Modified On : Wed Jan 31 22:29:25 2018 14 %% Update Count : 3147 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{ cquote}163 \begin{quote2} 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{ cquote}193 \end{quote2} 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 array:276 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating-point 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 values */ };284 double key = 5.0, vals[10] = { /* 10 sorted floating-point 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 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}§446 3.141®_®592®_®654; §\C{// floating point constant}§ 447 10®_®e®_®+1®_®00; §\C{// floating point constant}§ 448 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating point}§ 449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating point long constant}§ 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.1922i519 \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.524 503 525 504 … … 649 628 \end{cfa} 650 629 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: 651 \begin{ cquote}630 \begin{quote2} 652 631 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 653 632 \begin{cfa} … … 677 656 \end{cfa} 678 657 \end{tabular} 679 \end{ cquote}658 \end{quote2} 680 659 In this example, case 2 is always done if case 3 is done. 681 660 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. … … 751 730 ®int y = 1;® §\C{// unreachable initialization}§ 752 731 ®x = 7;® §\C{// unreachable code without label/branch}§ 753 case 0: ...732 case 3: ... 754 733 ... 755 734 ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§ 756 735 z = 2; 757 case 1:736 case 3: 758 737 ®x = z;® §\C{// without fall through, z is uninitialized}§ 759 738 } … … 840 819 Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C. 841 820 Therefore, the ©case© clause is extended with a list of values, as in: 842 \begin{ cquote}821 \begin{quote2} 843 822 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 844 823 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 870 849 \end{cfa} 871 850 \end{tabular} 872 \end{ cquote}851 \end{quote2} 873 852 In addition, two forms of subranges are allowed to specify case values: a new \CFA form and an existing GNU C form.\footnote{ 874 853 The GNU C form \emph{requires} spaces around the ellipse.} 875 \begin{ cquote}854 \begin{quote2} 876 855 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 877 856 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{GNU C}} \\ … … 903 882 \end{cfa} 904 883 \end{tabular} 905 \end{ cquote}884 \end{quote2} 906 885 Lists of subranges are also allowed. 907 886 \begin{cfa} … … 923 902 } 924 903 \end{C++} 925 Since \CFA is non-object-oriented, the equivalent object-oriented program looks like:904 Since CFA is non-object-oriented, the equivalent object-oriented program looks like: 926 905 \begin{cfa} 927 906 struct S { int i, j; }; 928 int mem( S & ®this® ) { §\C{// explicit "this" parameter}§907 int mem( S &®this® ) { §\C{// explicit "this" parameter}§ 929 908 ®this.®i = 1; §\C{// "this" is not elided}§ 930 909 ®this.®j = 2; 931 910 } 932 911 \end{cfa} 933 but it is cumbersome having to write ``©this.©''many times in a member.912 but it is cumbersome having to write "©this.©" many times in a member. 934 913 935 914 \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. 936 915 \begin{cfa} 937 int mem( S & this ) ®with this® { §\C{// with clause}§938 i = 1; §\C{\color{red}// this .i}§939 j = 2; §\C{\color{red}// this .j}§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}§ 940 919 } 941 920 \end{cfa} … … 943 922 \begin{cfa} 944 923 struct T { double m, n; }; 945 int mem2( S & this1, T &this2 ) ®with this1, this2® {924 int mem2( S &this1, T &this2 ) ®with this1, this2® { 946 925 i = 1; j = 2; 947 926 m = 1.0; n = 2.0; … … 954 933 struct S1 { ... } s1; 955 934 struct S2 { ... } s2; 956 ®with s1® { §\C{// with statement}§935 ®with s1® { // with statement 957 936 // access fields of s1 without qualification 958 ®with s2® { §\C{// nesting}§937 ®with s2® { // nesting 959 938 // access fields of s1 and s2 without qualification 960 939 } … … 1066 1045 1067 1046 1068 \section{ AlternativeDeclarations}1069 \label{s: AlternativeDeclarations}1047 \section{Declarations} 1048 \label{s:Declarations} 1070 1049 1071 1050 C declaration syntax is notoriously confusing and error prone. 1072 1051 For example, many C programmers are confused by a declaration as simple as: 1073 \begin{ cquote}1052 \begin{quote2} 1074 1053 \begin{tabular}{@{}ll@{}} 1075 1054 \begin{cfa} … … 1079 1058 \raisebox{-0.75\totalheight}{\input{Cdecl}} 1080 1059 \end{tabular} 1081 \end{ cquote}1060 \end{quote2} 1082 1061 Is this an array of 5 pointers to integers or a \Index{pointer} to an array of 5 integers? 1083 If there is any doubt, it implies\Index{productivity} and \Index{safety} issues even for basic programs.1062 The fact this declaration is unclear to many C programmers means there are \Index{productivity} and \Index{safety} issues even for basic programs. 1084 1063 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. 1085 1064 For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way: 1086 1065 \begin{cfa} 1087 int ®(*®f®())[®5®]® {...}; §\C{ //definition}§1088 ... ®(*®f®())[®3®]® += 1; §\C{ //usage}§1066 int ®(*®f®())[®5®]® {...}; §\C{definition}§ 1067 ... ®(*®f®())[®3®]® += 1; §\C{usage}§ 1089 1068 \end{cfa} 1090 1069 Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}). … … 1095 1074 In the following example, \R{red} is the base type and \B{blue} is qualifiers. 1096 1075 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. 1097 \begin{ cquote}1076 \begin{quote2} 1098 1077 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1099 1078 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1110 1089 \end{cfa} 1111 1090 \end{tabular} 1112 \end{ cquote}1091 \end{quote2} 1113 1092 The only exception is \Index{bit field} specification, which always appear to the right of the base type. 1114 1093 % 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. 1115 1094 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1116 1095 For instance, variables ©x© and ©y© of type \Index{pointer} to integer are defined in \CFA as follows: 1117 \begin{ cquote}1096 \begin{quote2} 1118 1097 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1119 1098 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1126 1105 \end{cfa} 1127 1106 \end{tabular} 1128 \end{ cquote}1107 \end{quote2} 1129 1108 The downside of this semantics is the need to separate regular and \Index{pointer} declarations: 1130 \begin{ cquote}1109 \begin{quote2} 1131 1110 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1132 1111 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ … … 1141 1120 \end{cfa} 1142 1121 \end{tabular} 1143 \end{ cquote}1122 \end{quote2} 1144 1123 which is \Index{prescribing} a safety benefit. 1145 1124 Other examples are: 1146 \begin{ cquote}1125 \begin{quote2} 1147 1126 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1148 1127 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 1180 1159 \end{cfa} 1181 1160 \end{tabular} 1182 \end{ cquote}1161 \end{quote2} 1183 1162 1184 1163 All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg: 1185 \begin{ cquote}1164 \begin{quote2} 1186 1165 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 1187 1166 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\ … … 1201 1180 \end{cfa} 1202 1181 \end{tabular} 1203 \end{ cquote}1182 \end{quote2} 1204 1183 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} 1205 1184 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: 1206 \begin{ cquote}1185 \begin{quote2} 1207 1186 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} 1208 1187 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\ … … 1222 1201 \end{cfa} 1223 1202 \end{tabular} 1224 \end{ cquote}1203 \end{quote2} 1225 1204 1226 1205 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©: 1227 \begin{ cquote}1206 \begin{quote2} 1228 1207 \begin{tabular}{@{}l@{\hspace{3em}}l@{}} 1229 1208 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1230 1209 \begin{cfa} 1231 y = ( * int)x;1232 i = sizeof( [ 5 ] * int);1210 y = (®* int®)x; 1211 i = sizeof(®[ 5 ] * int®); 1233 1212 \end{cfa} 1234 1213 & 1235 1214 \begin{cfa} 1236 y = ( int *)x;1237 i = sizeof( int * [ 5 ]);1215 y = (®int *®)x; 1216 i = sizeof(®int * [ 5 ]®); 1238 1217 \end{cfa} 1239 1218 \end{tabular} 1240 \end{ cquote}1219 \end{quote2} 1241 1220 1242 1221 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration. 1243 1222 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style. 1244 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems. 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. 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{ cquote}1262 \begin{quote2} 1263 1263 \begin{tabular}{@{}ll@{\hspace{2em}}l@{}} 1264 1264 \begin{cfa} … … 1278 1278 \end{cfa} 1279 1279 \end{tabular} 1280 \end{ cquote}1280 \end{quote2} 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{ cquote}1286 \begin{quote2} 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{ cquote}1304 \end{quote2} 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{ cquote}1311 \begin{quote2} 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{ cquote}1323 \end{quote2} 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: AlternativeDeclarations}) attempt to address this issue:1429 \begin{ cquote}1428 \CFA-style declarations (see \VRef{s:Declarations}) attempt to address this issue: 1429 \begin{quote2} 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{ cquote}1442 \end{quote2} 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: AlternativeDeclarations}), \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:Declarations}), \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{ cquote}2074 \begin{quote2} 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{ cquote}2089 \end{quote2} 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 value.2274 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating-point 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{ cquote}2997 \begin{quote2} 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{ cquote}3018 \end{quote2} 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{ cquote}3030 \begin{quote2} 3031 3031 \begin{tabular}{@{}ll@{}} 3032 3032 \textbf{\CFA:} … … 3047 3047 \end{cfa} 3048 3048 \end{tabular} 3049 \end{ cquote}3049 \end{quote2} 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{ cquote}3636 \begin{quote2} 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{ cquote}3660 \end{quote2} 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{ cquote}5723 \begin{quote2} 5724 5724 \input{../refrat/keywords} 5725 \end{ cquote}5725 \end{quote2} 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{ cquote}5732 \begin{quote2} 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{ cquote}5792 \end{quote2} 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{ cquote}6533 \begin{quote2} 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{ cquote}6565 \end{quote2} 6566 6566 6567 6567 \begin{figure} -
src/CodeGen/FixMain.cc
r7c782af rc71b256 39 39 { 40 40 if(main_signature) { 41 throw SemanticError( functionDecl, "Multiple definition of main routine\n");41 throw SemanticError("Multiple definition of main routine\n", functionDecl); 42 42 } 43 43 main_signature.reset( functionDecl->clone() ); -
src/CodeGen/FixNames.cc
r7c782af rc71b256 118 118 int nargs = functionDecl->get_functionType()->get_parameters().size(); 119 119 if( !(nargs == 0 || nargs == 2 || nargs == 3) ) { 120 throw SemanticError( functionDecl, "Main expected to have 0, 2 or 3 arguments\n");120 throw SemanticError("Main expected to have 0, 2 or 3 arguments\n", functionDecl); 121 121 } 122 122 functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) ); -
src/Common/PassVisitor.impl.h
r7c782af rc71b256 77 77 maybeAccept_impl( *i, visitor ); 78 78 } catch( SemanticError &e ) { 79 e.set_location( (*i)->location ); 79 80 errors.append( e ); 80 81 } … … 103 104 maybeMutate_impl( *i, mutator ); 104 105 } catch( SemanticError &e ) { 106 e.set_location( (*i)->location ); 105 107 errors.append( e ); 106 108 } … … 132 134 } 133 135 } catch( SemanticError &e ) { 136 e.set_location( (*i)->location ); 134 137 errors.append( e ); 135 138 } … … 160 163 } // if 161 164 } catch( SemanticError &e ) { 165 e.set_location( (*i)->location ); 162 166 errors.append( e ); 163 167 } // try … … 196 200 197 201 } catch ( SemanticError &e ) { 202 e.set_location( (*i)->location ); 198 203 errors.append( e ); 199 204 } -
src/Common/SemanticError.cc
r7c782af rc71b256 23 23 #include "SemanticError.h" 24 24 25 SemanticError::SemanticError( CodeLocation location, std::string error ) { 26 append( location, error ); 25 SemanticError::SemanticError() { 26 } 27 28 SemanticError::SemanticError( std::string error ) { 29 append( error ); 27 30 } 28 31 … … 31 34 } 32 35 33 void SemanticError::append( CodeLocation location,const std::string & msg ) {34 errors.emplace_back( location,msg );36 void SemanticError::append( const std::string & msg ) { 37 errors.emplace_back( error_str() + msg ); 35 38 } 36 39 … … 39 42 } 40 43 41 void SemanticError::print( ) {44 void SemanticError::print( std::ostream &os ) { 42 45 using std::to_string; 43 46 for( auto err : errors ) { 44 std::cerr << bold() << err.location << error_str() << reset_font()<< err.description << std::endl;47 os << err.location << err.description << std::endl; 45 48 } 46 49 } 47 50 48 SemanticWarning::SemanticWarning( CodeLocation location, std::string msg) {49 std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl;51 void SemanticError::set_location( const CodeLocation& location ) { 52 errors.begin()->maybeSet( location ); 50 53 } 51 54 -
src/Common/SemanticError.h
r7c782af rc71b256 24 24 #include "CodeLocation.h" // for CodeLocation, toString 25 25 26 //-----------------------------------------------------------------------------27 // Errors28 26 struct error { 27 std::string description; 29 28 CodeLocation location; 30 std::string description;31 29 32 30 error() = default; 33 error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {} 31 error( const std::string & str ) : description( str ) {} 32 33 void maybeSet( const CodeLocation & location ) { 34 if( this->location.isUnset() ) { 35 this->location = location; 36 } 37 } 34 38 }; 35 39 36 40 class SemanticError : public std::exception { 37 41 public: 38 SemanticError() = default; 39 SemanticError( CodeLocation location, std::string error ); 42 SemanticError(); 43 SemanticError( std::string error ); 44 template< typename T > SemanticError( const std::string & error, const T * obj ); 40 45 ~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);45 46 46 47 static inline const std::string & error_str() { … … 50 51 51 52 void append( SemanticError & other ); 52 void append( CodeLocation location,const std::string & );53 void append( const std::string & ); 53 54 bool isEmpty() const; 54 void print(); 55 void print( std::ostream & os ); 56 57 void set_location( const CodeLocation & location ); 58 // constructs an exception using the given message and the printed representation of the obj (T must have a print 59 // method) 55 60 private: 56 61 std::list< error > errors; … … 58 63 59 64 template< typename T > 60 SemanticError::SemanticError( const T * obj, const std::string & error ) 61 : SemanticError( obj->location, toString( error, obj ) ) 62 {} 63 64 template< typename T > 65 SemanticError::SemanticError( CodeLocation location, const T * obj, const std::string & error ) 66 : SemanticError( location, toString( error, obj ) ) 67 {} 68 69 //----------------------------------------------------------------------------- 70 // Warnings 71 class SemanticWarning { 72 public: 73 SemanticWarning( CodeLocation location, std::string error ); 74 ~SemanticWarning() throw() {} 75 76 // constructs an exception using the given message and the printed representation of the obj (T must have a print method) 77 template< typename T > SemanticWarning(const T * obj, const std::string & error); 78 template< typename T > SemanticWarning( CodeLocation location, const T * obj, const std::string & error); 79 80 static inline const std::string & warning_str() { 81 static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: "; 82 return str; 83 } 84 85 private: 86 }; 87 88 template< typename T > 89 SemanticWarning::SemanticWarning( const T * obj, const std::string & error ) 90 : SemanticWarning( obj->location, toString( error, obj ) ) 91 {} 92 93 template< typename T > 94 SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error ) 95 : SemanticWarning( location, toString( error, obj ) ) 96 {} 97 98 //----------------------------------------------------------------------------- 99 // Helpers 100 static inline const std::string & bold_ttycode() { 101 static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : ""; 102 return str; 103 } 104 105 static inline const std::string & reset_font_ttycode() { 106 static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : ""; 107 return str; 108 } 109 110 static inline std::string make_bold( const std::string & str ) { 111 return bold_ttycode() + str + reset_font_ttycode(); 112 } 113 114 struct bold {}; 115 static inline std::ostream & operator<<(std::ostream & os, bold) { 116 os << bold_ttycode(); 117 return os; 118 } 119 120 struct reset_font {}; 121 static inline std::ostream & operator<<(std::ostream & os, reset_font) { 122 os << reset_font_ttycode(); 123 return os; 65 SemanticError::SemanticError( const std::string & error, const T * obj ) { 66 append( toString( error, obj ) ); 124 67 } 125 68 -
src/Concurrency/Keywords.cc
r7c782af rc71b256 276 276 handle( decl ); 277 277 } 278 278 279 } 279 280 … … 281 282 if( ! decl->body ) return; 282 283 283 if( !type_decl ) throw SemanticError( decl, context_error);284 if( !type_decl ) throw SemanticError( context_error, decl ); 284 285 285 286 FunctionDecl * func = forwardDeclare( decl ); … … 418 419 if( mutexArgs.empty() ) return; 419 420 420 if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters");421 if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl ); 421 422 422 423 bool isDtor = CodeGen::isDestructor( decl->name ); 423 424 424 if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument");425 if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl ); 425 426 426 427 for(auto arg : mutexArgs) { … … 431 432 if( ! body ) return; 432 433 433 if( !monitor_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>");434 if( !guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>");435 if( !dtor_guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>");434 if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); 435 if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); 436 if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); 436 437 437 438 if( isDtor ) { … … 479 480 //Makes sure it's not a copy 480 481 ReferenceType* rty = dynamic_cast< ReferenceType * >( ty ); 481 if( ! rty ) throw SemanticError( arg, "Mutex argument must be of reference type ");482 if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg ); 482 483 483 484 //Make sure the we are pointing directly to a type 484 485 Type* base = rty->get_base(); 485 if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection ");486 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection ");486 if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); 487 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); 487 488 488 489 //Make sure that typed isn't mutex 489 if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument ");490 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg ); 490 491 } 491 492 … … 625 626 if( type && type->get_baseStruct()->is_thread() ) { 626 627 if( !thread_decl || !thread_ctor_seen ) { 627 throw SemanticError( type->get_baseStruct()->location,"thread keyword requires threads to be in scope, add #include <thread>");628 throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>"); 628 629 } 629 630 -
src/Concurrency/Waitfor.cc
r7c782af rc71b256 249 249 250 250 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) { 251 if( !decl_monitor || !decl_acceptable || !decl_mask ) 252 throw SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" ); 251 if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor ); 253 252 254 253 CompoundStmt * stmt = new CompoundStmt(); -
src/ControlStruct/ExceptTranslate.cc
r7c782af rc71b256 572 572 // Pass. 573 573 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 574 throw SemanticError( catchStmt->location,"catch must have exception type");574 throw SemanticError("catch must have exception type"); 575 575 } else { 576 throw SemanticError( catchStmt->location,"catchResume must have exception type");576 throw SemanticError("catchResume must have exception type"); 577 577 } 578 578 -
src/ControlStruct/LabelFixer.cc
r7c782af rc71b256 92 92 } else if ( labelTable[ l ]->defined() ) { 93 93 // defined twice, error 94 throw SemanticError( l.get_statement()->location,"Duplicate definition of label: " + l.get_name() );94 throw SemanticError( "Duplicate definition of label: " + l.get_name() ); 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( i->first.get_statement()->location,"Use of undefined label: " + i->first.get_name() );123 throw SemanticError( "Use of undefined label: " + i->first.get_name() ); 124 124 } 125 125 (*ret)[ i->first ] = i->second->get_definition(); -
src/ControlStruct/MLEMutator.cc
r7c782af rc71b256 115 115 } else { 116 116 // break target is outmost control structure 117 if ( enclosingControlStructures.empty() ) throw SemanticError( branchStmt->location,"'break' outside a loop, switch, or labelled block" );117 if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" ); 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( branchStmt->location,toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );126 throw SemanticError( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) ); 127 127 } // if 128 128 break; -
src/GenPoly/Box.cc
r7c782af rc71b256 229 229 } // if 230 230 } catch( SemanticError &e ) { 231 e.set_location( (*i)->location ); 231 232 errors.append( e ); 232 233 } // try … … 575 576 } 576 577 } else { 577 throw SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: ");578 throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType ); 578 579 } 579 580 } … … 597 598 } else { 598 599 // xxx - should this be an assertion? 599 throw SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ));600 throw SemanticError( toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ), appExpr ); 600 601 } // if 601 602 } // if -
src/InitTweak/FixInit.cc
r7c782af rc71b256 282 282 translationUnit.splice( i, fixer.pass.staticDtorDecls ); 283 283 } catch( SemanticError &e ) { 284 e.set_location( (*i)->location ); 284 285 errors.append( e ); 285 286 } // try … … 894 895 ) 895 896 if ( ! diff.empty() ) { 896 throw SemanticError( st mt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ");897 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 897 898 } // if 898 899 // S_G-S_L results in set of objects that must be destructed … … 1110 1111 template< typename Visitor, typename... Params > 1111 1112 void error( Visitor & v, CodeLocation loc, const Params &... params ) { 1112 SemanticError err( loc, toString( params... ) ); 1113 SemanticError err( toString( params... ) ); 1114 err.set_location( loc ); 1113 1115 v.errors.append( err ); 1114 1116 } -
src/InitTweak/GenInit.cc
r7c782af rc71b256 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( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n");319 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl ); 320 320 // constructed objects should not have initializers nested too deeply 321 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( objDecl, "Managed object's initializer is too deep ");321 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl ); 322 322 323 323 objDecl->set_init( genCtorInit( objDecl ) ); -
src/InitTweak/InitTweak.cc
r7c782af rc71b256 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( init->location,"unbalanced list initializers" );227 throw SemanticError( "unbalanced list initializers" ); 228 228 } 229 229 -
src/Parser/DeclarationNode.cc
r7c782af rc71b256 581 581 dst->basictype = src->basictype; 582 582 } else if ( src->basictype != DeclarationNode::NoBasicType ) 583 throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ");583 throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ", src ); 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( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ");588 throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ", src ); 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( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ");593 throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ", src ); 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( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ");600 throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ", src ); 601 601 } // if 602 602 break; … … 966 966 } // if 967 967 } catch( SemanticError &e ) { 968 e.set_location( cur->location ); 968 969 errors.append( e ); 969 970 } // try … … 1000 1001 } // if 1001 1002 } catch( SemanticError &e ) { 1003 e.set_location( cur->location ); 1002 1004 errors.append( e ); 1003 1005 } // try … … 1018 1020 * out++ = cur->buildType(); 1019 1021 } catch( SemanticError &e ) { 1022 e.set_location( cur->location ); 1020 1023 errors.append( e ); 1021 1024 } // try … … 1029 1032 1030 1033 Declaration * DeclarationNode::build() const { 1031 if ( ! error.empty() ) throw SemanticError( this, error + " in declaration of ");1034 if ( ! error.empty() ) throw SemanticError( error + " in declaration of ", this ); 1032 1035 1033 1036 if ( asmStmt ) { … … 1052 1055 // inline _Noreturn int i; // disallowed 1053 1056 if ( type->kind != TypeData::Function && funcSpecs.any() ) { 1054 throw SemanticError( this, "invalid function specifier for ");1057 throw SemanticError( "invalid function specifier for ", this ); 1055 1058 } // if 1056 1059 return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension ); … … 1062 1065 // inlne _Noreturn enum E { ... }; // disallowed 1063 1066 if ( funcSpecs.any() ) { 1064 throw SemanticError( this, "invalid function specifier for ");1067 throw SemanticError( "invalid function specifier for ", this ); 1065 1068 } // if 1066 1069 assertf( name, "ObjectDecl must a have name\n" ); -
src/Parser/ExpressionNode.cc
r7c782af rc71b256 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( yylloc,"invalid tuple index " + str );358 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( "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( yylloc,"invalid tuple index " + str );365 if ( str[str.size()-1] != '.' ) throw SemanticError( "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
r7c782af rc71b256 24 24 namespace LinkageSpec { 25 25 26 Spec linkageCheck( CodeLocation location,const string * spec ) {26 Spec linkageCheck( 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( location,"Invalid linkage specifier " + *spec );36 throw SemanticError( "Invalid linkage specifier " + *spec ); 37 37 } // if 38 38 } 39 39 40 Spec linkageUpdate( CodeLocation location,Spec old_spec, const string * cmd ) {40 Spec linkageUpdate( 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( location,"Invalid linkage specifier " + *cmd );50 throw SemanticError( "Invalid linkage specifier " + *cmd ); 51 51 } // if 52 52 } -
src/Parser/LinkageSpec.h
r7c782af rc71b256 17 17 18 18 #include <string> 19 20 #include "Common/CodeLocation.h"21 19 22 20 namespace LinkageSpec { … … 47 45 48 46 49 Spec linkageCheck( CodeLocation location,const std::string * );47 Spec linkageCheck( const std::string * ); 50 48 // Returns the Spec with the given name (limited to C, Cforall & BuiltinC) 51 Spec linkageUpdate( CodeLocation location,Spec old_spec, const std::string * cmd );49 Spec linkageUpdate( Spec old_spec, const std::string * cmd ); 52 50 /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false 53 51 * If cmd = "Cforall" returns old_spec Spec with is_mangled = true -
src/Parser/ParseNode.h
r7c782af rc71b256 434 434 } // if 435 435 } catch( SemanticError &e ) { 436 e.set_location( cur->location ); 436 437 errors.append( e ); 437 438 } // try -
src/Parser/TypeData.cc
r7c782af rc71b256 31 31 using namespace std; 32 32 33 TypeData::TypeData( Kind k ) : location( yylloc ),kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {33 TypeData::TypeData( Kind k ) : 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( yylloc,string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );523 throw SemanticError( 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, td->location,scs, typebuild( td->base ), linkage );802 ret = new TypedefDecl( name, 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( param->location,string( "duplicate declaration name " ) + *param->name );925 if ( param->type ) throw SemanticError( 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( param->location,string( "duplicate parameter name " ) + *param->name );928 if ( ! decl->type ) throw SemanticError( 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( decl->location,string( "missing name in parameter list " ) + *decl->name );935 if ( decl->type ) throw SemanticError( string( "missing name in parameter list " ) + *decl->name ); 936 936 } // for 937 937 -
src/Parser/TypeData.h
r7c782af rc71b256 76 76 }; 77 77 78 CodeLocation location;79 80 78 Kind kind; 81 79 TypeData * base; -
src/Parser/parser.yy
r7c782af rc71b256 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 15 17:12:31 201813 // Update Count : 300612 // Last Modified On : Thu Dec 21 11:32:56 2017 13 // Update Count : 2996 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( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; }// FIX ME484 { throw SemanticError("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( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME 487 | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11 488 { throw SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; } // FIX ME 489 ; 490 491 generic_assoc_list: // C11 492 | generic_association 493 | generic_assoc_list ',' generic_association 494 ; 495 496 generic_association: // C11 497 type_no_function ':' assignment_expression 498 | DEFAULT ':' assignment_expression 486 { throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; } // FIX ME 499 487 ; 500 488 … … 779 767 | unary_expression assignment_operator assignment_expression 780 768 { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); } 781 | unary_expression '=' '{' initializer_list comma_opt '}' // FIX ME782 { $$ = nullptr; }783 769 ; 784 770 … … 1064 1050 | RETURN comma_expression_opt ';' 1065 1051 { $$ = new StatementNode( build_return( $2 ) ); } 1066 | RETURN '{' initializer_list comma_opt '}' // FIX ME1067 { $$ = nullptr; }1068 1052 | THROW assignment_expression_opt ';' // handles rethrow 1069 1053 { $$ = new StatementNode( build_throw( $2 ) ); } … … 1084 1068 mutex_statement: 1085 1069 MUTEX '(' argument_expression_list ')' statement 1086 { throw SemanticError( yylloc, "Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME1070 { throw SemanticError("Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME 1087 1071 ; 1088 1072 … … 1305 1289 static_assert: 1306 1290 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1307 { throw SemanticError( yylloc, "Static assert is currently unimplemented."); $$ = nullptr; } // FIX ME1291 { throw SemanticError("Static assert is currently unimplemented."); $$ = nullptr; } // FIX ME 1308 1292 1309 1293 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function … … 2393 2377 { 2394 2378 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 2395 linkage = LinkageSpec::linkageUpdate( yylloc,linkage, $2 );2379 linkage = LinkageSpec::linkageUpdate( linkage, $2 ); 2396 2380 } 2397 2381 '{' external_definition_list_opt '}' -
src/ResolvExpr/AlternativeFinder.cc
r7c782af rc71b256 239 239 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 240 240 ) 241 throw SemanticError( expr, "No reasonable alternatives for expression ");241 throw SemanticError( "No reasonable alternatives for expression ", expr ); 242 242 } 243 243 if ( prune ) { … … 257 257 stream << "Alternatives are:\n"; 258 258 printAlts( winners, stream, 1 ); 259 throw SemanticError( expr->location,stream.str() );259 throw SemanticError( stream.str() ); 260 260 } 261 261 alternatives = move(pruned); … … 494 494 return; 495 495 } else if ( level >= recursionLimit ) { 496 throw SemanticError( newAlt.expr->location,"Too many recursive assertions" );496 throw SemanticError( "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( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: ");1410 throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() ); 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( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: ");1431 throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() ); 1432 1432 } // if 1433 1433 // return the lowest cost alternative for the argument -
src/ResolvExpr/CurrentObject.cc
r7c782af rc71b256 141 141 base = at->get_base(); 142 142 memberIter = createMemberIterator( base ); 143 if ( at->isVarLen ) throw SemanticError( at, "VLA initialization does not support @=");143 if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at ); 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( expr, "Constant expression of non-integral type in array dimension: ");158 throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr ); 159 159 } 160 160 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { … … 179 179 index = constExpr->intValue(); 180 180 } catch( SemanticError & ) { 181 throw SemanticError( expr, "Constant expression of non-integral type in array designator: ");181 throw SemanticError( "Constant expression of non-integral type in array designator: ", expr ); 182 182 } 183 183 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { … … 532 532 } // for 533 533 if ( desigAlts.size() > 1 ) { 534 throw SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: "));534 throw SemanticError( toString("Too many alternatives (", desigAlts.size(), ") for designation: "), designation ); 535 535 } else if ( desigAlts.size() == 0 ) { 536 throw SemanticError( designation, "No reasonable alternatives for designation: ");536 throw SemanticError( "No reasonable alternatives for designation: ", designation ); 537 537 } 538 538 DesignatorChain & d = desigAlts.back(); -
src/ResolvExpr/Resolver.cc
r7c782af rc71b256 174 174 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 175 175 if ( winners.size() == 0 ) { 176 throw SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: "));176 throw SemanticError( toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: "), untyped ); 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( untyped->location,stream.str() );183 throw SemanticError( stream.str() ); 184 184 } 185 185 … … 187 187 Alternative & choice = winners.front(); 188 188 if ( findDeletedExpr( choice.expr ) ) { 189 throw SemanticError( choice.expr, "Unique best alternative includes deleted identifier in ");189 throw SemanticError( "Unique best alternative includes deleted identifier in ", choice.expr ); 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 tmt->location, ss.str() );486 throw SemanticError( 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( func.expr->get_result(), "candidate not viable: not a pointer type\n");508 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() ); 509 509 } 510 510 511 511 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 512 512 if( !function ) { 513 throw SemanticError( pointer->get_base(), "candidate not viable: not a function type\n");513 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() ); 514 514 } 515 515 … … 520 520 521 521 if( !advance_to_mutex( param, param_end ) ) { 522 throw SemanticError( function, "candidate function not viable: no mutex parameters\n");522 throw SemanticError("candidate function not viable: no mutex parameters\n", function); 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( function, "candidate function not viable: too many mutex arguments\n");561 throw SemanticError("candidate function not viable: too many mutex arguments\n", function); 562 562 } 563 563 … … 571 571 (*param)->get_type()->print( ss ); 572 572 ss << "'\n"; 573 throw SemanticError( function, ss.str());573 throw SemanticError(ss.str(), function); 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( function, "candidate function not viable: too few mutex arguments\n");585 throw SemanticError("candidate function not viable: too few mutex arguments\n", function); 586 586 } 587 587 … … 610 610 611 611 // Make sure we got the right number of arguments 612 if( func_candidates.empty() ) { SemanticError top( stmt->location,"No alternatives for function in call to waitfor" ); top.append( errors ); throw top; }613 if( args_candidates.empty() ) { SemanticError top( stmt->location,"No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }614 if( func_candidates.size() > 1 ) { SemanticError top( stmt->location,"Ambiguous function in call to waitfor" ); top.append( errors ); throw top; }615 if( args_candidates.size() > 1 ) { SemanticError top( stmt->location,"Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; }612 if( func_candidates.empty() ) { SemanticError top( "No alternatives for function in call to waitfor" ); top.append( errors ); throw top; } 613 if( args_candidates.empty() ) { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; } 614 if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 615 if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 616 616 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 617 617 -
src/SymTab/Indexer.cc
r7c782af rc71b256 443 443 // isomorphic to C type-compatibility, which it may not be. 444 444 if ( hasIncompatibleCDecl( name, mangleName, scope ) ) { 445 throw SemanticError( decl, "conflicting overload of C function ");445 throw SemanticError( "conflicting overload of C function ", decl ); 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( decl, "Cforall declaration hides C function ");450 throw SemanticError( "Cforall declaration hides C function ", decl ); 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( decl, msg); return true; }, baseExpr );465 addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); 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( decl, msg); return true; }, nullptr, deleteStmt );470 addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); return true; }, nullptr, deleteStmt ); 471 471 } 472 472 … … 477 477 return true; 478 478 } else { 479 throw SemanticError( added, "redeclaration of ");479 throw SemanticError( "redeclaration of ", added ); 480 480 } 481 481 } … … 504 504 return false; 505 505 } else if ( ! added->get_members().empty() ) { 506 throw SemanticError( added, "redeclaration of ");506 throw SemanticError( "redeclaration of ", added ); 507 507 } // if 508 508 return true; -
src/SymTab/Validate.cc
r7c782af rc71b256 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( func, "invalid type void in function type ");363 throw SemanticError( "invalid type void in function type ", func ); 364 364 } 365 365 … … 402 402 for ( Expression * param : inst->parameters ) { 403 403 if ( ! dynamic_cast< TypeExpr * >( param ) ) { 404 throw SemanticError( inst, "Expression parameters for generic types are currently unsupported: ");404 throw SemanticError( "Expression parameters for generic types are currently unsupported: ", inst ); 405 405 } 406 406 } … … 502 502 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name ); 503 503 if ( ! traitDecl ) { 504 throw SemanticError( traitInst->location,"use of undeclared trait " + traitInst->name );504 throw SemanticError( "use of undeclared trait " + traitInst->name ); 505 505 } // if 506 506 if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) { 507 throw SemanticError( traitInst, "incorrect number of trait parameters: ");507 throw SemanticError( "incorrect number of trait parameters: ", traitInst ); 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( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: ");515 throw SemanticError( "Expression parameters for trait instances are currently unsupported: ", std::get<1>(p) ); 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( node, "invalid type void in assertion of function ");621 throw SemanticError( "invalid type void in assertion of function ", node ); 622 622 } // if 623 623 } // for … … 663 663 // were cast to void. 664 664 if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) { 665 throw SemanticError( returnStmt, "Non-void function returns no values: ");665 throw SemanticError( "Non-void function returns no values: " , returnStmt ); 666 666 } 667 667 } … … 704 704 ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret); 705 705 if ( ! rtt ) { 706 throw SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name);706 throw SemanticError("Cannot apply type parameters to base type of " + typeInst->name); 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( tyDecl->location,"Cannot redefine typedef: " + tyDecl->name );744 throw SemanticError( "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( tyDecl->location,"Cannot redefine typedef: " + tyDecl->name );751 throw SemanticError( "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(), aggDecl->location,Type::StorageClasses(), type, aggDecl->get_linkage() ) );849 TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), 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( funcDecl, "Constructors, destructors, and assignment functions require at least one parameter ");900 throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl ); 901 901 } 902 902 ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() ); 903 903 if ( ! refType ) { 904 throw SemanticError( funcDecl, "First parameter of a constructor, destructor, or assignment function must be a reference ");904 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl ); 905 905 } 906 906 if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) { 907 throw SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values ");907 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl ); 908 908 } 909 909 } … … 940 940 941 941 sub.apply( inst ); 942 if ( args.size() < params->size() ) throw SemanticError( inst, "Too few type arguments in generic type ");943 if ( args.size() > params->size() ) throw SemanticError( inst, "Too many type arguments in generic type ");942 if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst ); 943 if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst ); 944 944 } 945 945 } -
src/SynTree/Declaration.h
r7c782af rc71b256 245 245 typedef NamedTypeDecl Parent; 246 246 public: 247 TypedefDecl( const std::string &name, CodeLocation location, Type::StorageClasses scs, Type *type, LinkageSpec::Spec spec = LinkageSpec::Cforall ) 248 : Parent( name, scs, type ) { set_linkage( spec ); this->location = location; } 249 247 TypedefDecl( const std::string &name, Type::StorageClasses scs, Type *type, LinkageSpec::Spec spec = LinkageSpec::Cforall ) : Parent( name, scs, type ) { set_linkage( spec ); } 250 248 TypedefDecl( const TypedefDecl &other ) : Parent( other ) {} 251 249 -
src/SynTree/Expression.cc
r7c782af rc71b256 93 93 return 0; 94 94 } 95 throw SemanticError( this, "Constant expression of non-integral type ");95 throw SemanticError( "Constant expression of non-integral type ", this ); 96 96 } 97 97 -
src/SynTree/Mutator.h
r7c782af rc71b256 149 149 } // if 150 150 } catch( SemanticError &e ) { 151 e.set_location( (*i)->location ); 151 152 errors.append( e ); 152 153 } // try -
src/SynTree/Statement.cc
r7c782af rc71b256 100 100 //actually this is a syntactic error signaled by the parser 101 101 if ( type == BranchStmt::Goto && target.empty() ) { 102 throw SemanticError( target.get_statement()->location,"goto without target");102 throw SemanticError("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( computedTarget->location,"Computed target not valid in branch statement");109 throw SemanticError("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( condition, "default case with condition: ");205 if ( isDefault() && condition != 0 ) throw SemanticError("default case with condition: ", condition); 206 206 } 207 207 -
src/SynTree/TypeSubstitution.h
r7c782af rc71b256 98 98 } // if 99 99 } else { 100 throw SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ));100 throw SemanticError( toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ), formal ); 101 101 } // if 102 102 } else { -
src/SynTree/Visitor.h
r7c782af rc71b256 143 143 } 144 144 } catch( SemanticError &e ) { 145 e.set_location( (*i)->location ); 145 146 errors.append( e ); 146 147 } -
src/libcfa/concurrency/alarm.c
r7c782af rc71b256 18 18 #include <stdio.h> 19 19 #include <string.h> 20 #include <time.h> 20 21 #include <unistd.h> 21 22 #include <sys/time.h> … … 26 27 #include "preemption.h" 27 28 28 29 static inline void ?{}( itimerval & this, __cfa_time_t * alarm ) with( this ) { 30 it_value.tv_sec = alarm->val / (1`cfa_s).val; // seconds 31 it_value.tv_usec = max( (alarm->val % (1`cfa_s).val) / (1`cfa_us).val, 1000 ); // microseconds 29 //============================================================================================= 30 // time type 31 //============================================================================================= 32 33 #define one_second 1_000_000_000ul 34 #define one_milisecond 1_000_000ul 35 #define one_microsecond 1_000ul 36 #define one_nanosecond 1ul 37 38 __cfa_time_t zero_time = { 0 }; 39 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 32 46 it_interval.tv_sec = 0; 33 47 it_interval.tv_usec = 0; 34 48 } 35 49 36 static inline void ?{}( __cfa_time_t & this, timespec * curr ) { 50 51 void ?{}( __cfa_time_t & this, timespec * curr ) { 37 52 uint64_t secs = curr->tv_sec; 38 53 uint64_t nsecs = curr->tv_nsec; 39 this.val = from_s(secs).val + nsecs; 40 } 54 this.val = (secs * one_second) + nsecs; 55 } 56 57 __cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ) { 58 this.val = 0; 59 return this; 60 } 61 62 __cfa_time_t from_s ( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1_000_000_000ul; return ret; } 63 __cfa_time_t from_ms( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1_000_000ul; return ret; } 64 __cfa_time_t from_us( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1_000ul; return ret; } 65 __cfa_time_t from_ns( uint64_t val ) { __cfa_time_t ret; ret.val = val * 1ul; return ret; } 41 66 42 67 //============================================================================================= … … 59 84 //============================================================================================= 60 85 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 ) {86 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) { 62 87 this.thrd = thrd; 63 88 this.alarm = alarm; … … 68 93 } 69 94 70 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = 0`cfa_s, __cfa_time_t period = 0`cfa_s) with( this ) {95 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) with( this ) { 71 96 this.proc = proc; 72 97 this.alarm = alarm; -
src/libcfa/concurrency/alarm.h
r7c782af rc71b256 21 21 #include <assert.h> 22 22 23 #include "bits/cfatime.h"24 25 23 struct thread_desc; 26 24 struct processor; 25 26 struct timespec; 27 struct itimerval; 28 29 //============================================================================================= 30 // time type 31 //============================================================================================= 32 33 struct __cfa_time_t { 34 uint64_t val; 35 }; 36 37 // ctors 38 void ?{}( __cfa_time_t & this ); 39 void ?{}( __cfa_time_t & this, zero_t zero ); 40 void ?{}( __cfa_time_t & this, timespec * curr ); 41 void ?{}( itimerval & this, __cfa_time_t * alarm ); 42 43 __cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ); 44 45 // logical ops 46 static inline bool ?==?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val == rhs.val; } 47 static inline bool ?!=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val != rhs.val; } 48 static inline bool ?>? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val > rhs.val; } 49 static inline bool ?<? ( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val < rhs.val; } 50 static inline bool ?>=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val >= rhs.val; } 51 static inline bool ?<=?( __cfa_time_t lhs, __cfa_time_t rhs ) { return lhs.val <= rhs.val; } 52 53 static inline bool ?==?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val == rhs; } 54 static inline bool ?!=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val != rhs; } 55 static inline bool ?>? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val > rhs; } 56 static inline bool ?<? ( __cfa_time_t lhs, zero_t rhs ) { return lhs.val < rhs; } 57 static inline bool ?>=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val >= rhs; } 58 static inline bool ?<=?( __cfa_time_t lhs, zero_t rhs ) { return lhs.val <= rhs; } 59 60 // addition/substract 61 static inline __cfa_time_t ?+?( __cfa_time_t lhs, __cfa_time_t rhs ) { 62 __cfa_time_t ret; 63 ret.val = lhs.val + rhs.val; 64 return ret; 65 } 66 67 static inline __cfa_time_t ?-?( __cfa_time_t lhs, __cfa_time_t rhs ) { 68 __cfa_time_t ret; 69 ret.val = lhs.val - rhs.val; 70 return ret; 71 } 72 73 __cfa_time_t from_s ( uint64_t ); 74 __cfa_time_t from_ms( uint64_t ); 75 __cfa_time_t from_us( uint64_t ); 76 __cfa_time_t from_ns( uint64_t ); 77 78 extern __cfa_time_t zero_time; 27 79 28 80 //============================================================================================= … … 53 105 typedef alarm_node_t ** __alarm_it_t; 54 106 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);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 ); 57 109 void ^?{}( alarm_node_t & this ); 58 110 -
src/libcfa/concurrency/coroutine.c
r7c782af rc71b256 99 99 // Wrapper for co 100 100 void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 101 verify( preemption.enabled || this_processor->do_terminate );102 101 disable_interrupts(); 103 102 … … 117 116 118 117 enable_interrupts( __cfaabi_dbg_ctx ); 119 verify( preemption.enabled || this_processor->do_terminate );120 118 } //ctxSwitchDirect 121 119 -
src/libcfa/concurrency/invoke.c
r7c782af rc71b256 28 28 extern void __suspend_internal(void); 29 29 extern void __leave_coroutine(void); 30 extern void __finish_creation(void);31 30 extern void __leave_thread_monitor( struct thread_desc * this ); 32 31 extern void disable_interrupts(); … … 45 44 46 45 cor->state = Active; 47 48 enable_interrupts( __cfaabi_dbg_ctx );49 46 50 47 main( this ); … … 65 62 // First suspend, once the thread arrives here, 66 63 // the function pointer to main can be invalidated without risk 67 __ finish_creation();64 __suspend_internal(); 68 65 69 66 // Fetch the thread handle from the user defined thread structure -
src/libcfa/concurrency/kernel.c
r7c782af rc71b256 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; 61 62 volatile thread_local __cfa_kernel_preemption_data_t preemption = { false, false, 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; 63 61 64 62 //----------------------------------------------------------------------------- … … 209 207 if(readyThread) 210 208 { 211 verify( !preemption .enabled );209 verify( !preemption_enabled ); 212 210 213 211 runThread(this, readyThread); 214 212 215 verify( !preemption .enabled );213 verify( !preemption_enabled ); 216 214 217 215 //Some actions need to be taken from the kernel … … 262 260 void finishRunning(processor * this) with( this->finish ) { 263 261 if( action_code == Release ) { 264 verify( !preemption .enabled );262 verify( !preemption_enabled ); 265 263 unlock( *lock ); 266 264 } … … 269 267 } 270 268 else if( action_code == Release_Schedule ) { 271 verify( !preemption .enabled );269 verify( !preemption_enabled ); 272 270 unlock( *lock ); 273 271 ScheduleThread( thrd ); 274 272 } 275 273 else if( action_code == Release_Multi ) { 276 verify( !preemption .enabled );274 verify( !preemption_enabled ); 277 275 for(int i = 0; i < lock_count; i++) { 278 276 unlock( *locks[i] ); … … 306 304 this_coroutine = NULL; 307 305 this_thread = NULL; 308 preemption .enabled = false;309 preemption.disable_count = 1;306 preemption_enabled = false; 307 disable_preempt_count = 1; 310 308 // SKULLDUGGERY: We want to create a context for the processor coroutine 311 309 // which is needed for the 2-step context switch. However, there is no reason … … 347 345 } 348 346 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 inactive364 src->state = src->state == Halted ? Halted : Inactive;365 366 // set new coroutine that task is executing367 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 will373 // stay disabled.374 disable_interrupts();375 376 // context switch to specified coroutine377 assert( src->stack.context );378 CtxSwitch( src->stack.context, dst->stack.context );379 // when CtxSwitch returns we are back in the src coroutine380 381 // set state of new coroutine to active382 src->state = Active;383 384 verify( !preemption.enabled );385 }386 387 347 //----------------------------------------------------------------------------- 388 348 // Scheduler routines … … 392 352 verify( thrd->self_cor.state != Halted ); 393 353 394 verify( !preemption .enabled );354 verify( !preemption_enabled ); 395 355 396 356 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); … … 402 362 } 403 363 404 verify( !preemption .enabled );364 verify( !preemption_enabled ); 405 365 } 406 366 407 367 thread_desc * nextThread(cluster * this) with( *this ) { 408 verify( !preemption .enabled );368 verify( !preemption_enabled ); 409 369 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 410 370 thread_desc * head = pop_head( ready_queue ); 411 371 unlock( ready_queue_lock ); 412 verify( !preemption .enabled );372 verify( !preemption_enabled ); 413 373 return head; 414 374 } … … 416 376 void BlockInternal() { 417 377 disable_interrupts(); 418 verify( !preemption .enabled );419 returnToKernel(); 420 verify( !preemption .enabled );378 verify( !preemption_enabled ); 379 returnToKernel(); 380 verify( !preemption_enabled ); 421 381 enable_interrupts( __cfaabi_dbg_ctx ); 422 382 } … … 427 387 this_processor->finish.lock = lock; 428 388 429 verify( !preemption .enabled );430 returnToKernel(); 431 verify( !preemption .enabled );389 verify( !preemption_enabled ); 390 returnToKernel(); 391 verify( !preemption_enabled ); 432 392 433 393 enable_interrupts( __cfaabi_dbg_ctx ); … … 439 399 this_processor->finish.thrd = thrd; 440 400 441 verify( !preemption .enabled );442 returnToKernel(); 443 verify( !preemption .enabled );401 verify( !preemption_enabled ); 402 returnToKernel(); 403 verify( !preemption_enabled ); 444 404 445 405 enable_interrupts( __cfaabi_dbg_ctx ); … … 453 413 this_processor->finish.thrd = thrd; 454 414 455 verify( !preemption .enabled );456 returnToKernel(); 457 verify( !preemption .enabled );415 verify( !preemption_enabled ); 416 returnToKernel(); 417 verify( !preemption_enabled ); 458 418 459 419 enable_interrupts( __cfaabi_dbg_ctx ); … … 466 426 this_processor->finish.lock_count = count; 467 427 468 verify( !preemption .enabled );469 returnToKernel(); 470 verify( !preemption .enabled );428 verify( !preemption_enabled ); 429 returnToKernel(); 430 verify( !preemption_enabled ); 471 431 472 432 enable_interrupts( __cfaabi_dbg_ctx ); … … 481 441 this_processor->finish.thrd_count = thrd_count; 482 442 483 verify( !preemption .enabled );484 returnToKernel(); 485 verify( !preemption .enabled );443 verify( !preemption_enabled ); 444 returnToKernel(); 445 verify( !preemption_enabled ); 486 446 487 447 enable_interrupts( __cfaabi_dbg_ctx ); … … 489 449 490 450 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) { 491 verify( !preemption .enabled );451 verify( !preemption_enabled ); 492 452 this_processor->finish.action_code = thrd ? Release_Schedule : Release; 493 453 this_processor->finish.lock = lock; … … 503 463 // Kernel boot procedures 504 464 void kernel_startup(void) { 505 verify( !preemption.enabled );506 465 __cfaabi_dbg_print_safe("Kernel : Starting\n"); 507 466 … … 541 500 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 542 501 // mainThread is on the ready queue when this call is made. 543 kernel_first_resume( this_processor );502 resume( *mainProcessor->runner ); 544 503 545 504 … … 548 507 __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n"); 549 508 550 verify( !preemption.enabled );551 509 enable_interrupts( __cfaabi_dbg_ctx ); 552 verify( preemption.enabled );553 510 } 554 511 … … 556 513 __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n"); 557 514 558 verify( preemption.enabled );559 515 disable_interrupts(); 560 verify( !preemption.enabled );561 516 562 517 // SKULLDUGGERY: Notify the mainProcessor it needs to terminates. -
src/libcfa/concurrency/kernel_private.h
r7c782af rc71b256 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; 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; 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; 87 79 88 80 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/monitor.c
r7c782af rc71b256 10 10 // Created On : Thd Feb 23 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 16 14:49:53201813 // Update Count : 512 // Last Modified On : Thu Feb 8 16:12:20 2018 13 // Update Count : 4 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 % zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );429 abort( "Signal on condition %p made with different number of monitor(s), expected %li got %li", &this, this.monitor_count, this_thrd->monitors.size ); 430 430 } 431 431 -
src/libcfa/concurrency/preemption.c
r7c782af rc71b256 149 149 // Disable interrupts by incrementing the counter 150 150 void disable_interrupts() { 151 preemption .enabled = false;152 __attribute__((unused)) unsigned short new_val = preemption.disable_count + 1;153 preemption.disable_count = new_val;151 preemption_enabled = false; 152 __attribute__((unused)) unsigned short new_val = disable_preempt_count + 1; 153 disable_preempt_count = new_val; 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 = preemption.disable_count;164 preemption.disable_count -= 1;163 unsigned short prev = disable_preempt_count; 164 disable_preempt_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 = preemption.disable_count;184 preemption.disable_count -= 1;183 unsigned short prev = disable_preempt_count; 184 disable_preempt_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 preemption.disable_count = 1;252 preemption_enabled = false; 253 disable_preempt_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, 0`cfa_s, 0`cfa_s};292 (this.alarm){ proc, zero_time, zero_time }; 293 293 this.proc = proc; 294 294 this.proc->preemption_alarm = &this.alarm; … … 300 300 disable_interrupts(); 301 301 302 update_preemption( this.proc, 0`cfa_s);302 update_preemption( this.proc, zero_time ); 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
r7c782af rc71b256 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 99 92 void yield( void ) { 100 verify( preemption.enabled );101 93 BlockInternal( this_thread ); 102 verify( preemption.enabled );103 94 } 104 95 -
src/main.cc
r7c782af rc71b256 282 282 } // if 283 283 284 CodeTools::fillLocations( translationUnit );285 286 284 OPTPRINT( "resolve" ) 287 285 ResolvExpr::resolve( translationUnit ); … … 363 361 cerr << endl << "---End of AST, begin error message:---\n" << endl; 364 362 } // if 365 e.print( );363 e.print( cerr ); 366 364 if ( output != &cout ) { 367 365 delete output; -
src/tests/.expect/alloc.txt
r7c782af rc71b256 2 2 CFA malloc 0xdeadbeef 3 3 CFA alloc 0xdeadbeef 4 CFA alloc, fill ffffffff4 CFA alloc, fill 01010101 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 ff13 0x ffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff12 CFA array alloc, fill 0x1 13 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 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 ffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff27 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 28 28 CFA resize array alloc, fill 29 0x ffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff29 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 30 30 CFA resize array alloc, fill 31 0x ffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff31 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 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 ffffffff -nan39 CFA align_alloc fill 0x1010101 0x1.1010101010101p-1007 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 ffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,44 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 45 45 46 CFA memset 0x ffffffff -nan47 CFA memcpy 0x ffffffff -nan46 CFA memset 0x1010101 0x1.1010101010101p-1007 47 CFA memcpy 0x1010101 0x1.1010101010101p-1007 48 48 49 49 CFA array memset 50 0x ffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,50 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 51 51 CFA memcpy 52 0x ffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan, 0xffffffff -nan,52 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 0x1010101 0x1.1010101010101p-1007, 53 53 54 54 CFA new initialize -
src/tests/alloc.c
r7c782af rc71b256 10 10 // Created On : Wed Feb 3 07:56:22 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Feb 16 15:42:31201813 // Update Count : 3 3012 // Last Modified On : Mon Jan 22 21:26:40 2018 13 // Update Count : 326 14 14 // 15 15 … … 27 27 int main( void ) { 28 28 size_t dim = 10; 29 char fill = '\xff';30 29 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 %# hhx\n", fill );81 printf( "CFA array alloc, fill %#x\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
r7c782af rc71b256 1 raii/dtor-early-exit.c:2 17:1 error: jump to label 'L2' crosses initialization of y Branch (Goto)1 raii/dtor-early-exit.c:220: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.