Changeset caa649b
- Timestamp:
- Mar 6, 2018, 12:11:11 PM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 520145b, e5d4e5c, e6c5e79
- Parents:
- 094476d (diff), 1feb535f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 2 added
- 2 deleted
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/bibliography/pl.bib
r094476d rcaa649b 6687 6687 contributer = {pabuhr@plg}, 6688 6688 author = {{TIOBE Index}}, 6689 year = { March 2017},6689 year = {February 2018}, 6690 6690 url = {http://www.tiobe.com/tiobe_index}, 6691 6691 } -
doc/papers/general/Paper.tex
r094476d rcaa649b 13 13 \usepackage{pslatex} % reduce size of san serif font 14 14 \usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref} 15 \urlstyle{sf} 16 \usepackage{breakurl} 15 17 16 18 \setlength{\textheight}{9in} … … 199 201 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. 200 202 This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more. 201 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.203 The TIOBE~\cite{TIOBE} ranks the top 5 most \emph{popular} programming languages as: Java 15\%, \Textbf{C 12\%}, \Textbf{\CC 5.5\%}, Python 5\%, \Csharp 4.5\% = 42\%, where the next 50 languages are less than 4\% each with a long tail. 202 204 The top 3 rankings over the past 30 years are: 203 205 \begin{center} … … 205 207 \lstDeleteShortInline@% 206 208 \begin{tabular}{@{}rccccccc@{}} 207 & 201 7 & 2012 & 2007 & 2002 & 1997 & 1992 & 1987\\ \hline208 Java & 1 & 1 & 1 & 1 & 12 & - & -\\209 \Textbf{C} & \Textbf{2}& \Textbf{2}& \Textbf{2}& \Textbf{2}& \Textbf{1}& \Textbf{1}& \Textbf{1}\\210 \CC & 3 & 3 & 3 & 3 & 2 & 2 & 4\\209 & 2018 & 2013 & 2008 & 2003 & 1998 & 1993 & 1988 \\ \hline 210 Java & 1 & 2 & 1 & 1 & 18 & - & - \\ 211 \Textbf{C}& \Textbf{2} & \Textbf{1} & \Textbf{2} & \Textbf{2} & \Textbf{1} & \Textbf{1} & \Textbf{1} \\ 212 \CC & 3 & 4 & 3 & 3 & 2 & 2 & 5 \\ 211 213 \end{tabular} 212 214 \lstMakeShortInline@% … … 227 229 \CFA is currently implemented as a source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3). 228 230 Ultimately, a compiler is necessary for advanced features and optimal performance. 229 230 This paper identifies shortcomings in existing approaches to generic and variadic data types in C-like languages and presents a design for generic and variadic types avoiding those shortcomings. 231 All of the features discussed in this paper are working, unless a feature states it is a future feature for completion. 232 233 234 \section{Polymorphic Functions} 235 236 \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}. 237 Shortcomings are identified in existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA. 231 238 Specifically, the solution is both reusable and type-checked, as well as conforming to the design goals of \CFA with ergonomic use of existing C abstractions. 232 The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance. 233 234 \section{Polymorphic Functions} 235 236 \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}. 239 The new constructs are empirically compared with C and \CC approaches via performance experiments in Section~\ref{sec:eval}. 240 237 241 238 242 \subsection{Name Overloading} 239 243 \label{s:NameOverloading} 244 245 \begin{quote} 246 There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton 247 \end{quote} 240 248 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. 241 249 \CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable; … … 245 253 246 254 \begin{cfa} 247 int max(int a, int b) { return a < b ? b : a; } // (1) 248 double max(double a, double b) { return a < b ? b : a; } // (2) 249 250 int max = INT_MAX; // (3) 251 double max = DBL_MAX; // (4) 252 253 max(7, -max); $\C{// uses (1) and (3), by matching int from constant 7}$ 254 max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$ 255 256 //max(max, -max); $\C{// ERROR: ambiguous}$ 257 int m = max(max, -max); $\C{// uses (1) once and (3) twice, by matching return type}$ 258 \end{cfa} 259 260 \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. 255 int max = 2147483647; $\C[3.75in]{// (1)}$ 256 double max = 1.7976931348623157E+308; $\C{// (2)}$ 257 int max( int a, int b ) { return a < b ? b : a; } $\C{// (3)}$ 258 double max( double a, double b ) { return a < b ? b : a; } $\C{// (4)}\CRT$ 259 max( 7, -max ); $\C{// uses (3) and (1), by matching int from constant 7}$ 260 max( max, 3.14 ); $\C{// uses (4) and (2), by matching double from constant 3.14}$ 261 max( max, -max ); $\C{// ERROR: ambiguous}$ 262 int m = max( max, -max ); $\C{// uses (3) and (1) twice, by matching return type}$ 263 \end{cfa} 264 \CFA maximizes the ability to reuse names to aggressively address the naming problem. 265 In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction for a programmer. 266 In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum. 267 To prevent significant ambiguities, \CFA uses the return type in selecting overloads, \eg in the assignment to @m@, the compiler use @m@'s type to unambiguously select the most appropriate call to function @max@ (as does Ada). 268 As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities. 269 270 \Celeven added @_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. 261 271 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@. 262 272 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. 263 Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA does implement@_Generic@ for backwards-compatibility purposes. \TODO{actually implement that}273 Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA implements @_Generic@ for backwards-compatibility purposes. \TODO{actually implement that} 264 274 265 275 % http://fanf.livejournal.com/144696.html … … 288 298 For example, the function @twice@ can be defined using the \CFA syntax for operator overloading: 289 299 \begin{cfa} 290 forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x +x; } $\C{// ? denotes operands}$300 forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; } $\C{// ? denotes operands}$ 291 301 int val = twice( twice( 3.7 ) ); 292 302 \end{cfa} … … 343 353 \begin{cfa} 344 354 forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ } 345 { int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$ 355 { 356 int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$ 346 357 qsort( vals, size ); $\C{// descending sort}$ 347 358 } … … 414 425 \section{Generic Types} 415 426 416 One of the known shortcomings of standard C is that it does not providereusable type-safe abstractions for generic data structures and algorithms.427 A significant shortcoming of standard C is the lack of reusable type-safe abstractions for generic data structures and algorithms. 417 428 Broadly speaking, there are three approaches to implement abstract data-structures in C. 418 429 One approach is to write bespoke data-structures for each context in which they are needed. 419 430 While this approach is flexible and supports integration with the C type-checker and tooling, it is also tedious and error-prone, especially for more complex data structures. 420 A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@ ; an approach which does allow reuse of code forcommon functionality.421 However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that would not otherwise be needed.431 A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allows reuse of code with common functionality. 432 However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is not otherwise needed. 422 433 A third approach to generic code is to use preprocessor macros, which does allow the generated code to be both generic and type-checked, but errors may be difficult to interpret. 423 434 Furthermore, writing and using preprocessor macros can be unnatural and inflexible. … … 434 445 }; 435 446 forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; } 436 forall( dtype F, otype T ) T value _p( pair( F *, T * ) p ) { return *p.second; }447 forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; } 437 448 438 449 pair( const char *, int ) p = { "magic", 42 }; 439 int magic= value( p );450 int i = value( p ); 440 451 pair( void *, int * ) q = { 0, &p.second }; 441 magic = value_p( q );452 i = value( q ); 442 453 double d = 1.0; 443 454 pair( double *, double * ) r = { &d, &d }; 444 d = value _p( r );455 d = value( r ); 445 456 \end{cfa} 446 457 … … 589 600 [ double ] foo$\(_2\)$( int ); 590 601 void bar( int, double, double ); 591 bar( foo( 3 ), foo( 3 ) );602 `bar`( foo( 3 ), foo( 3 ) ); 592 603 \end{cfa} 593 604 The type-resolver only has the tuple return-types to resolve the call to @bar@ as the @foo@ parameters are identical, which involves unifying the possible @foo@ functions with @bar@'s parameter list. … … 835 846 Since @sum@\(_0\) does not accept any arguments, it is not a valid candidate function for the call @sum(10, 20, 30)@. 836 847 In order to call @sum@\(_1\), @10@ is matched with @x@, and the argument resolution moves on to the argument pack @rest@, which consumes the remainder of the argument list and @Params@ is bound to @[20, 30]@. 837 The process continues un itl @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.848 The process continues until @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion. 838 849 Effectively, this algorithm traces as @sum(10, 20, 30)@ $\rightarrow$ @10 + sum(20, 30)@ $\rightarrow$ @10 + (20 + sum(30))@ $\rightarrow$ @10 + (20 + (30 + sum()))@ $\rightarrow$ @10 + (20 + (30 + 0))@. 839 850 … … 979 990 \section{Control Structures} 980 991 981 \CFA identifies missing and problematic control structures in C, and extends and modifies these control structures to increase functionality and safety. 992 \CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds to control structures to increase functionality and safety. 993 994 995 \subsection{\texorpdfstring{\LstKeywordStyle{if} Statement}{if Statement}} 996 997 The @if@ expression allows declarations, similar to @for@ declaration expression: 998 \begin{cfa} 999 if ( int x = f() ) ... $\C{// x != 0}$ 1000 if ( int x = f(), y = g() ) ... $\C{// x != 0 \&\& y != 0}$ 1001 if ( int x = f(), y = g(); `x < y` ) ... $\C{// relational expression}$ 1002 \end{cfa} 1003 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the @if@ expression, and the results are combined using the logical @&&@ operator.\footnote{\CC only provides a single declaration always compared not equal to 0.} 1004 The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses. 1005 1006 1007 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 1008 1009 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. 1010 1011 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.}. 1012 \CFA provides a shorthand for a non-contiguous list: 1013 \begin{cquote} 1014 \lstDeleteShortInline@% 1015 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1016 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1017 \begin{cfa} 1018 case 2, 10, 34, 42: 1019 \end{cfa} 1020 & 1021 \begin{cfa} 1022 case 2: case 10: case 34: case 42: 1023 \end{cfa} 1024 \end{tabular} 1025 \lstMakeShortInline@% 1026 \end{cquote} 1027 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1028 \begin{cquote} 1029 \lstDeleteShortInline@% 1030 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1031 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1032 \begin{cfa} 1033 case 2~42: 1034 \end{cfa} 1035 & 1036 \begin{cfa} 1037 case 2: case 3: ... case 41: case 42: 1038 \end{cfa} 1039 \end{tabular} 1040 \lstMakeShortInline@% 1041 \end{cquote} 1042 and a combination: 1043 \begin{cfa} 1044 case -12~-4, -1~5, 14~21, 34~42: 1045 \end{cfa} 1046 1047 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1048 \begin{cfa} 1049 switch ( i ) { 1050 case 0: 1051 for ( int i = 0; i < 10; i += 1 ) { 1052 ... 1053 `case 1:` // no initialization of loop index 1054 ... 1055 } 1056 } 1057 \end{cfa} 1058 \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. 1059 1060 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1061 \begin{cfa} 1062 switch ( x ) { 1063 `int y = 1;` $\C{// unreachable initialization}$ 1064 `x = 7;` $\C{// unreachable code without label/branch}$ 1065 case 0: 1066 ... 1067 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1068 z = 2; 1069 case 1: 1070 `x = z;` $\C{// without fall through, z is undefined}$ 1071 } 1072 \end{cfa} 1073 \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. 1074 \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. 1075 1076 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}; 1077 @case@ clauses are made disjoint by the @break@ statement. 1078 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. 1079 For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}). 1080 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1081 1082 \begin{figure} 1083 \centering 1084 \lstDeleteShortInline@% 1085 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1086 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1087 \begin{cfa} 1088 `choose` ( day ) { 1089 case Mon~Thu: // program 1090 1091 case Fri: // program 1092 wallet += pay; 1093 `fallthrough;` 1094 case Sat: // party 1095 wallet -= party; 1096 1097 case Sun: // rest 1098 1099 default: // error 1100 } 1101 \end{cfa} 1102 & 1103 \begin{cfa} 1104 switch ( day ) { 1105 case Mon: case Tue: case Wed: case Thu: // program 1106 `break;` 1107 case Fri: // program 1108 wallet += pay; 1109 1110 case Sat: // party 1111 wallet -= party; 1112 `break;` 1113 case Sun: // rest 1114 `break;` 1115 default: // error 1116 } 1117 \end{cfa} 1118 \end{tabular} 1119 \lstMakeShortInline@% 1120 \caption{\lstinline|choose| versus \lstinline|switch| Statements} 1121 \label{f:ChooseSwitchStatements} 1122 \end{figure} 1123 1124 \begin{comment} 1125 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. 1126 \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. 1127 Since empty cases like @case 7:@ in @case 7: case 11:@ still have fall-through semantics and explicit @break@ is still allowed at the end of a @choose@ case, many idiomatic uses of @switch@ in standard C can be converted to @choose@ statements by simply changing the keyword. 1128 Where fall-through is desired for a non-empty case, it can be specified with the new @fallthrough@ statement, making @choose@ equivalently powerful to @switch@, but more concise in the common case where most non-empty cases end with a @break@ statement, as in the example below: 1129 1130 \begin{cfa} 1131 choose( i ) { 1132 case 2: 1133 printf("even "); 1134 fallthrough; 1135 case 3: case 5: case 7: 1136 printf("small prime\n"); 1137 case 4,6,8,9: 1138 printf("small composite\n"); 1139 case 13~19: 1140 printf("teen\n"); 1141 default: 1142 printf("something else\n"); 1143 } 1144 \end{cfa} 1145 \end{comment} 982 1146 983 1147 … … 1039 1203 } else { 1040 1204 ... goto `LIF`; ... 1041 } `L 3:` ;1205 } `LIF:` ; 1042 1206 } `LS:` ; 1043 1207 } `LC:` ; … … 1089 1253 1090 1254 1091 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}} 1092 1093 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. 1094 1095 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.}. 1096 \CFA provides a shorthand for a non-contiguous list: 1255 \subsection{Exception Handling} 1256 1257 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts. 1258 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}). 1259 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler. 1260 \CFA restricts exception types to those defined by aggregate type @exception@. 1261 The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@). 1262 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation. 1263 If there is no current exception, the reresume/rethrow results in a runtime error. 1264 1265 \begin{figure} 1097 1266 \begin{cquote} 1098 1267 \lstDeleteShortInline@% 1099 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1100 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1101 \begin{cfa} 1102 case 2, 10, 34, 42: 1103 \end{cfa} 1104 & 1105 \begin{cfa} 1106 case 2: case 10: case 34: case 42: 1268 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1269 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\ 1270 \begin{cfa} 1271 `exception R { int fix; };` 1272 void f() { 1273 R r; 1274 ... `resume( r );` ... 1275 ... r.fix // control does return here after handler 1276 } 1277 `try` { 1278 ... f(); ... 1279 } `catchResume( R r )` { 1280 ... r.fix = ...; // return correction to raise 1281 } // dynamic return to _Resume 1282 \end{cfa} 1283 & 1284 \begin{cfa} 1285 `exception T {};` 1286 void f() { 1287 1288 ... `throw( T{} );` ... 1289 // control does NOT return here after handler 1290 } 1291 `try` { 1292 ... f(); ... 1293 } `catch( T t )` { 1294 ... // recover and continue 1295 } // static return to next statement 1107 1296 \end{cfa} 1108 1297 \end{tabular} 1109 1298 \lstMakeShortInline@% 1110 1299 \end{cquote} 1111 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1300 \caption{\CFA Exception Handling} 1301 \label{f:CFAExceptionHandling} 1302 \end{figure} 1303 1304 The set of exception types in a list of catch clause may include both a resumption and termination handler: 1305 \begin{cfa} 1306 try { 1307 ... resume( `R{}` ); ... 1308 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$ 1309 catch( `R` r ) { ... } $\C{\color{red}// H2}$ 1310 1311 \end{cfa} 1312 The resumption propagation raises @R@ and the stack is not unwound; 1313 the exception is caught by the @catchResume@ clause and handler H1 is invoked. 1314 The termination propagation in handler H1 raises @R@ and the stack is unwound; 1315 the exception is caught by the @catch@ clause and handler H2 is invoked. 1316 The termination handler is available because the resumption propagation did not unwind the stack. 1317 1318 An additional feature is conditional matching in a catch clause: 1319 \begin{cfa} 1320 try { 1321 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$ 1322 ... write( `logfile`, ... ); ... 1323 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$ 1324 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$ 1325 catch ( IOError err ) { ... } $\C{// handler error from other files}$ 1326 \end{cfa} 1327 where the throw inserts the failing file-handle in the I/O exception. 1328 Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible.. 1329 1330 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}: 1331 \begin{cfa} 1332 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ ) 1333 resume( $\emph{alternate-stack}$ ) 1334 \end{cfa} 1335 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}. 1336 Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns. 1337 1338 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation. 1339 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks: 1112 1340 \begin{cquote} 1113 1341 \lstDeleteShortInline@% 1114 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1115 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1116 \begin{cfa} 1117 case 2~42: 1118 \end{cfa} 1119 & 1120 \begin{cfa} 1121 case 2: case 3: ... case 41: case 42: 1342 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1343 \begin{cfa} 1344 enable $\emph{exception-type-list}$ { 1345 // allow non-local resumption 1346 } 1347 \end{cfa} 1348 & 1349 \begin{cfa} 1350 disable $\emph{exception-type-list}$ { 1351 // disallow non-local resumption 1352 } 1122 1353 \end{cfa} 1123 1354 \end{tabular} 1124 1355 \lstMakeShortInline@% 1125 1356 \end{cquote} 1126 and a combination: 1127 \begin{cfa} 1128 case -12~-4, -1~5, 14~21, 34~42: 1129 \end{cfa} 1130 1131 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1132 \begin{cfa} 1133 switch ( i ) { 1134 case 0: 1135 for ( int i = 0; i < 10; i += 1 ) { 1136 ... 1137 `case 1:` // no initialization of loop index 1138 ... 1139 } 1140 } 1141 \end{cfa} 1142 \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. 1143 1144 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1145 \begin{cfa} 1146 switch ( x ) { 1147 `int y = 1;` $\C{// unreachable initialization}$ 1148 `x = 7;` $\C{// unreachable code without label/branch}$ 1149 case 0: 1150 ... 1151 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1152 z = 2; 1153 case 1: 1154 `x = z;` $\C{// without fall through, z is undefined}$ 1155 } 1156 \end{cfa} 1157 \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. 1158 \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. 1159 1160 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}; 1161 @case@ clauses are made disjoint by the @break@ statement. 1162 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. 1163 For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through: 1164 \begin{cquote} 1165 \lstDeleteShortInline@% 1166 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1167 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1168 \begin{cfa} 1169 `choose` ( day ) { 1170 case Mon~Thu: // program 1171 1172 case Fri: // program 1173 wallet += pay; 1174 `fallthrough;` 1175 case Sat: // party 1176 wallet -= party; 1177 1178 case Sun: // rest 1179 1180 default: // error 1181 } 1182 \end{cfa} 1183 & 1184 \begin{cfa} 1185 switch ( day ) { 1186 case Mon: case Tue: case Wed: case Thu: // program 1187 `break;` 1188 case Fri: // program 1189 wallet += pay; 1190 1191 case Sat: // party 1192 wallet -= party; 1193 `break;` 1194 case Sun: // rest 1195 `break;` 1196 default: // error 1197 } 1198 \end{cfa} 1199 \end{tabular} 1200 \lstMakeShortInline@% 1201 \end{cquote} 1202 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1203 1204 \begin{comment} 1205 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. 1206 \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. 1207 Since empty cases like @case 7:@ in @case 7: case 11:@ still have fall-through semantics and explicit @break@ is still allowed at the end of a @choose@ case, many idiomatic uses of @switch@ in standard C can be converted to @choose@ statements by simply changing the keyword. 1208 Where fall-through is desired for a non-empty case, it can be specified with the new @fallthrough@ statement, making @choose@ equivalently powerful to @switch@, but more concise in the common case where most non-empty cases end with a @break@ statement, as in the example below: 1209 1210 \begin{cfa} 1211 choose( i ) { 1212 case 2: 1213 printf("even "); 1214 fallthrough; 1215 case 3: case 5: case 7: 1216 printf("small prime\n"); 1217 case 4,6,8,9: 1218 printf("small composite\n"); 1219 case 13~19: 1220 printf("teen\n"); 1221 default: 1222 printf("something else\n"); 1223 } 1224 \end{cfa} 1225 \end{comment} 1357 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively. 1358 Specifying no exception type is shorthand for specifying all exception types. 1359 Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state. 1360 1361 Finally, \CFA provides a Java like @finally@ clause after the catch clauses: 1362 \begin{cfa} 1363 try { 1364 ... f(); ... 1365 // catchResume or catch clauses 1366 } `finally` { 1367 // house keeping 1368 } 1369 \end{cfa} 1370 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised. 1371 If an exception is raised and caught, the handler is run before the finally clause. 1372 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated. 1373 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses. 1226 1374 1227 1375 … … 1238 1386 S s, as[10]; 1239 1387 \end{cfa} 1240 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:1388 However, functions manipulating aggregates must repeat the aggregate name to access its containing fields: 1241 1389 \begin{cfa} 1242 1390 void f( S s ) { … … 1256 1404 } 1257 1405 \end{C++} 1258 Object-oriented nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.1406 Object-oriented nesting of member functions in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping. 1259 1407 However, for other aggregate parameters, qualification is necessary: 1260 1408 \begin{cfa} … … 1286 1434 'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$ 1287 1435 \end{cfa} 1288 and may appear as the body of a routine or nested within a routinebody.1436 and may appear as the body of a function or nested within a function body. 1289 1437 Each expression in the expression-list provides a type and object. 1290 1438 The type must be an aggregate type. … … 1313 1461 Qualification or a cast is used to disambiguate. 1314 1462 1315 There is an interesting problem between parameters and the routine@with@, \eg:1463 There is an interesting problem between parameters and the function @with@, \eg: 1316 1464 \begin{cfa} 1317 1465 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ … … 1319 1467 } 1320 1468 \end{cfa} 1321 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the routine@with@.1469 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function @with@. 1322 1470 To solve this problem, parameters are treated like an initialized aggregate: 1323 1471 \begin{cfa} … … 1327 1475 } params; 1328 1476 \end{cfa} 1329 and implicitly opened \emph{after} a routineopen, to give them higher priority:1477 and implicitly opened \emph{after} a function open, to give them higher priority: 1330 1478 \begin{cfa} 1331 1479 void ?{}( S & s, int i ) with ( s ) `with( $\emph{\color{red}params}$ )` { … … 1355 1503 1356 1504 1357 \subsection{Exception Handling}1358 1359 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.1360 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).1361 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.1362 \CFA restricts exception types to those defined by aggregate type @exception@.1363 The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@).1364 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.1365 If there is no current exception, the reresume/rethrow results in a runtime error.1366 1367 \begin{figure}1368 \begin{cquote}1369 \lstDeleteShortInline@%1370 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}1371 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Recovery}} \\1372 \begin{cfa}1373 `exception R { int fix; };`1374 void f() {1375 R r;1376 ... `resume( r );` ...1377 ... r.fix // control does return here after handler1378 }1379 `try` {1380 ... f(); ...1381 } `catchResume( R r )` {1382 ... r.fix = ...; // return correction to raise1383 } // dynamic return to _Resume1384 \end{cfa}1385 &1386 \begin{cfa}1387 `exception T {};`1388 void f() {1389 1390 ... `throw( T{} );` ...1391 // control does NOT return here after handler1392 }1393 `try` {1394 ... f(); ...1395 } `catch( T t )` {1396 ... // recover and continue1397 } // static return to next statement1398 \end{cfa}1399 \end{tabular}1400 \lstMakeShortInline@%1401 \end{cquote}1402 \caption{\CFA Exception Handling}1403 \label{f:CFAExceptionHandling}1404 \end{figure}1405 1406 The set of exception types in a list of catch clause may include both a resumption and termination handler:1407 \begin{cfa}1408 try {1409 ... resume( `R{}` ); ...1410 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$1411 catch( `R` r ) { ... } $\C{\color{red}// H2}$1412 1413 \end{cfa}1414 The resumption propagation raises @R@ and the stack is not unwound;1415 the exception is caught by the @catchResume@ clause and handler H1 is invoked.1416 The termination propagation in handler H1 raises @R@ and the stack is unwound;1417 the exception is caught by the @catch@ clause and handler H2 is invoked.1418 The termination handler is available because the resumption propagation did not unwind the stack.1419 1420 An additional feature is conditional matching in a catch clause:1421 \begin{cfa}1422 try {1423 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$1424 ... write( `logfile`, ... ); ...1425 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$1426 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$1427 catch ( IOError err ) { ... } $\C{// handler error from other files}$1428 \end{cfa}1429 where the throw inserts the failing file-handle in the I/O exception.1430 Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible..1431 1432 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:1433 \begin{cfa}1434 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )1435 resume( $\emph{alternate-stack}$ )1436 \end{cfa}1437 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.1438 Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns.1439 1440 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.1441 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:1442 \begin{cquote}1443 \lstDeleteShortInline@%1444 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}1445 \begin{cfa}1446 enable $\emph{exception-type-list}$ {1447 // allow non-local resumption1448 }1449 \end{cfa}1450 &1451 \begin{cfa}1452 disable $\emph{exception-type-list}$ {1453 // disallow non-local resumption1454 }1455 \end{cfa}1456 \end{tabular}1457 \lstMakeShortInline@%1458 \end{cquote}1459 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.1460 Specifying no exception type is shorthand for specifying all exception types.1461 Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state.1462 1463 Finally, \CFA provides a Java like @finally@ clause after the catch clauses:1464 \begin{cfa}1465 try {1466 ... f(); ...1467 // catchResume or catch clauses1468 } `finally` {1469 // house keeping1470 }1471 \end{cfa}1472 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.1473 If an exception is raised and caught, the handler is run before the finally clause.1474 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.1475 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.1476 1477 1478 1505 \section{Declarations} 1479 1506 … … 1503 1530 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers? 1504 1531 If there is any doubt, it implies productivity and safety issues even for basic programs. 1505 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.1506 For example, a routinereturning a pointer to an array of integers is defined and used in the following way:1532 Another example of confusion results from the fact that a function name and its parameters are embedded within the return type, mimicking the way the return value is used at the function's call site. 1533 For example, a function returning a pointer to an array of integers is defined and used in the following way: 1507 1534 \begin{cfa} 1508 1535 int `(*`f`())[`5`]` {...}; $\C{// definition}$ 1509 1536 ... `(*`f`())[`3`]` += 1; $\C{// usage}$ 1510 1537 \end{cfa} 1511 Essentially, the return type is wrapped around the routinename in successive layers (like an onion).1538 Essentially, the return type is wrapped around the function name in successive layers (like an onion). 1512 1539 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice. 1513 1540 1514 \CFA provides its own type, variable and routinedeclarations, using a different syntax.1541 \CFA provides its own type, variable and function declarations, using a different syntax. 1515 1542 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right. 1516 1543 The qualifiers have the same meaning but are ordered left to right to specify a variable's type. … … 1540 1567 \end{cquote} 1541 1568 The only exception is bit field specification, which always appear to the right of the base type. 1542 % 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 routineparameter.1569 % 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 function parameter. 1543 1570 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1544 1571 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows: … … 1626 1653 \lstMakeShortInline@% 1627 1654 \end{cquote} 1628 Specifiers must appear at the start of a \CFA routinedeclaration\footnote{\label{StorageClassSpecifier}1655 Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier} 1629 1656 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}}. 1630 1657 1631 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo- routine@sizeof@:1658 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@: 1632 1659 \begin{cquote} 1633 1660 \lstDeleteShortInline@% … … 1647 1674 \end{cquote} 1648 1675 1649 The syntax of the new routine prototype declaration follows directly from the new routinedefinition syntax;1676 The syntax of the new function-prototype declaration follows directly from the new function-definition syntax; 1650 1677 as well, parameter names are optional, \eg: 1651 1678 \begin{cfa} … … 1656 1683 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$ 1657 1684 \end{cfa} 1658 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routinedefinition header (or vice versa).1659 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routinenames in the declaration list, \eg:1685 This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa). 1686 Like C, it is possible to declare multiple function-prototypes in a single declaration, where the return type is distributed across \emph{all} function names in the declaration list, \eg: 1660 1687 \begin{cquote} 1661 1688 \lstDeleteShortInline@% … … 1672 1699 \lstMakeShortInline@% 1673 1700 \end{cquote} 1674 where \CFA allows the last routinein the list to define its body.1675 1676 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:1677 \begin{cfa} 1678 * [ int x ] () fp; $\C{// pointer to routinereturning int with no parameters}$1679 * [ * int ] ( int y ) gp; $\C{// pointer to routinereturning pointer to int with int parameter}$1680 * [ ] ( int, char ) hp; $\C{// pointer to routinereturning no result with int and char parameters}$1681 * [ * int, int ] ( int ) jp; $\C{// pointer to routinereturning pointer to int and int, with int parameter}$1682 \end{cfa} 1683 Note, a routinename cannot be specified:1684 \begin{cfa} 1685 * [ int x ] f () fp; $\C{// routinename "f" is disallowed}$1701 where \CFA allows the last function in the list to define its body. 1702 1703 The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg: 1704 \begin{cfa} 1705 * [ int x ] () fp; $\C{// pointer to function returning int with no parameters}$ 1706 * [ * int ] ( int y ) gp; $\C{// pointer to function returning pointer to int with int parameter}$ 1707 * [ ] ( int, char ) hp; $\C{// pointer to function returning no result with int and char parameters}$ 1708 * [ * int, int ] ( int ) jp; $\C{// pointer to function returning pointer to int and int, with int parameter}$ 1709 \end{cfa} 1710 Note, a function name cannot be specified: 1711 \begin{cfa} 1712 * [ int x ] f () fp; $\C{// function name "f" is disallowed}$ 1686 1713 \end{cfa} 1687 1714 … … 1903 1930 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}. 1904 1931 \begin{cfa} 1905 struct VLA { 1906 int len, * data; 1907 }; 1908 void ?{}( VLA & vla ) with ( vla ) { $\C{// default constructor}$ 1909 len = 10; data = alloc( len ); $\C{// shallow copy}$ 1910 } 1911 void ^?{}( VLA & vla ) with ( vla ) { $\C{// destructor}$ 1912 free( data ); 1913 } 1932 struct VLA { int len, * data; }; 1933 void ?{}( VLA & vla ) with ( vla ) { len = 10; data = alloc( len ); } $\C{// default constructor}$ 1934 void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$ 1914 1935 { 1915 1936 VLA x; $\C{// implicit: ?\{\}( x );}$ 1916 1937 } $\C{// implicit: ?\^{}\{\}( x );}$ 1917 1938 \end{cfa} 1918 (Note, the example is purposely kept simple by using shallow-copy semantics.)1919 1939 @VLA@ is a \newterm{managed type}\footnote{ 1920 1940 A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a field of a managed type. … … 1924 1944 \CFA also provides syntax for \newterm{initialization} and \newterm{copy}: 1925 1945 \begin{cfa} 1926 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { 1946 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { $\C{// initialization}$ 1927 1947 len = size; data = alloc( len, fill ); 1928 1948 } 1929 void ?{}( VLA & vla, VLA other ) { $\C{// copy }$1949 void ?{}( VLA & vla, VLA other ) { $\C{// copy, shallow}$ 1930 1950 vla.len = other.len; vla.data = other.data; 1931 1951 } 1932 1952 \end{cfa} 1953 (Note, the example is purposely kept simple by using shallow-copy semantics.) 1933 1954 An initialization constructor-call has the same syntax as a C initializer, except the initialization values are passed as arguments to a matching constructor (number and type of paremeters). 1934 1955 \begin{cfa} … … 1944 1965 \begin{cfa} 1945 1966 { 1946 VLA x, y = { 20, 0x01 }, z = y;1947 // implicit: ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); z points to y1967 VLA x, y = { 20, 0x01 }, z = y; $\C{// z points to y}$ 1968 // ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); 1948 1969 ^x{}; $\C{// deallocate x}$ 1949 1970 x{}; $\C{// reallocate x}$ … … 1952 1973 y{ x }; $\C{// reallocate y, points to x}$ 1953 1974 x{}; $\C{// reallocate x, not pointing to y}$ 1954 // implicit:^?{}(z); ^?{}(y); ^?{}(x);1975 // ^?{}(z); ^?{}(y); ^?{}(x); 1955 1976 } 1956 1977 \end{cfa} … … 1983 2004 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. 1984 2005 In keeping with the general \CFA approach of adding features while respecting the ``C-style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backwards-compatible semantics. 1985 A trivial example is allowing the underscore to separate prefixes, digits, and suffixes in all \CFA constants, as in Ada, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@. 2006 A trivial example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@. 2007 2008 2009 \subsection{Integral Suffixes} 2010 2011 Additional integral suffixes are added to cover all the integral types and lengths. 2012 \begin{cquote} 2013 \lstDeleteShortInline@% 2014 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2015 \begin{cfa} 2016 20`_hh` // signed char 2017 21`_hhu` // unsigned char 2018 22`_h` // signed short int 2019 23`_uh` // unsigned short int 2020 24`z` // size_t 2021 \end{cfa} 2022 & 2023 \begin{cfa} 2024 20`_L8` // int8_t 2025 21`_ul8` // uint8_t 2026 22`_l16` // int16_t 2027 23`_ul16` // uint16_t 2028 24`_l32` // int32_t 2029 \end{cfa} 2030 & 2031 \begin{cfa} 2032 25`_ul32` // uint32_t 2033 26`_l64` // int64_t 2034 27`_l64u` // uint64_t 2035 26`_L128` // int128 2036 27`_L128u` // unsigned int128 2037 \end{cfa} 2038 \end{tabular} 2039 \lstMakeShortInline@% 2040 \end{cquote} 1986 2041 1987 2042 … … 2000 2055 2001 2056 2002 \subsection{Integral Suffixes} 2003 2004 Additional integral suffixes are added to cover all the integral types and lengths. 2005 \begin{cquote} 2057 \subsection{User Literals} 2058 2059 For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours). 2060 The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call-syntax (literal argument before function name), using the backquote, to convert basic literals into user literals. 2061 The backquote is a small character, making the unit (function name) predominate. 2062 For examples, the multi-precision integers in Section~\ref{s:MultiPrecisionIntegers} make use of user literals: 2063 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2064 \begin{cfa} 2065 y = 9223372036854775807L|`mp| * 18446744073709551615UL|`mp|; 2066 y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|; 2067 \end{cfa} 2068 Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions. 2069 }% 2070 2071 The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax. 2072 However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals. 2073 After which, user literals must match (no conversions); 2074 hence, it is necessary to overload the unit with all appropriate types. 2075 Finally, the use of the single quote as a separator is restricted to digits, precluding its use in the literal prefix or suffix, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote. 2076 2077 \begin{figure} 2078 \centering 2079 \lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2006 2080 \lstDeleteShortInline@% 2007 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2008 \begin{cfa} 2009 20_hh // signed char 2010 21_hhu // unsigned char 2011 22_h // signed short int 2012 23_uh // unsigned short int 2013 24z // size_t 2014 \end{cfa} 2015 & 2016 \begin{cfa} 2017 20_L8 // int8_t 2018 21_ul8 // uint8_t 2019 22_l16 // int16_t 2020 23_ul16 // uint16_t 2021 24_l32 // int32_t 2022 \end{cfa} 2023 & 2024 \begin{cfa} 2025 25_ul32 // uint32_t 2026 26_l64 // int64_t 2027 27_l64u // uint64_t 2028 26_L128 // int128 2029 27_L128u // unsigned int128 2081 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2082 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 2083 \begin{cfa} 2084 struct W { 2085 double stones; 2086 }; 2087 void ?{}( W & w ) { w.stones = 0; } 2088 void ?{}( W & w, double w ) { w.stones = w; } 2089 W ?+?( W l, W r ) { 2090 return (W){ l.stones + r.stones }; 2091 } 2092 W |?`st|( double w ) { return (W){ w }; } 2093 W |?`lb|( double w ) { return (W){ w / 14.0 }; } 2094 W |?`kg|( double w ) { return (W) { w * 0.16 }; } 2095 2096 2097 2098 int main() { 2099 W w, heavy = { 20 }; 2100 w = 155|`lb|; 2101 w = 0b_1111|`st|; 2102 w = 0_233|`lb|; 2103 w = 0x_9b_u|`kg|; 2104 w = 5.5|`st| + 8|`kg| + 25.01|`lb| + heavy; 2105 } 2106 \end{cfa} 2107 & 2108 \begin{cfa} 2109 struct W { 2110 double stones; 2111 W() { stones = 0.0; } 2112 W( double w ) { stones = w; } 2113 }; 2114 W operator+( W l, W r ) { 2115 return W( l.stones + r.stones ); 2116 } 2117 W |operator"" _st|( unsigned long long int w ) { return W( w ); } 2118 W |operator"" _lb|( unsigned long long int w ) { return W( w / 14.0 ); } 2119 W |operator"" _kg|( unsigned long long int w ) { return W( w * 0.16 ); } 2120 W |operator"" _st|( long double w ) { return W( w ); } 2121 W |operator"" _lb|( long double w ) { return W( w / 14.0 ); } 2122 W |operator"" _kg|( long double w ) { return W( w * 0.16 ); } 2123 int main() { 2124 W w, heavy = { 20 }; 2125 w = 155|_lb|; 2126 w = 0b1111|_lb|; // error, binary unsupported 2127 w = 0${\color{red}'}$233|_lb|; // quote separator 2128 w = 0x9b|_kg|; 2129 w = 5.5d|_st| + 8|_kg| + 25.01|_lb| + heavy; 2130 } 2030 2131 \end{cfa} 2031 2132 \end{tabular} 2032 2133 \lstMakeShortInline@% 2033 \end{cquote} 2034 2035 2036 \subsection{Units} 2037 2038 Alternative call syntax (literal argument before routine name) to convert basic literals into user literals. 2039 2040 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2041 \begin{cfa} 2042 struct Weight { double stones; }; 2043 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$ 2044 void ?{}( Weight & w, double w ) { w.stones = w; } 2045 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } 2046 2047 Weight |?`st|( double w ) { return (Weight){ w }; } $\C{// backquote for units}$ 2048 Weight |?`lb|( double w ) { return (Weight){ w / 14.0 }; } 2049 Weight |?`kg|( double w ) { return (Weight) { w * 0.1575}; } 2050 2051 int main() { 2052 Weight w, heavy = { 20 }; $\C{// 20 stone}$ 2053 w = 155|`lb|; 2054 w = 0x_9b_u|`lb|; $\C{// hexadecimal unsigned weight (155)}$ 2055 w = 0_233|`lb|; $\C{// octal weight (155)}$ 2056 w = 5|`st| + 8|`kg| + 25|`lb| + heavy; 2057 } 2058 \end{cfa} 2059 }% 2134 \caption{User Literal} 2135 \label{f:UserLiteral} 2136 \end{figure} 2060 2137 2061 2138 … … 2067 2144 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime. 2068 2145 The following sections give a glimpse of the interface reduction to many C libraries. 2069 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.2146 In many cases, @signed@/@unsigned@ @char@, @short@, and @_Complex@ functions are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results. 2070 2147 2071 2148 … … 2095 2172 \begin{cquote} 2096 2173 \lstDeleteShortInline@% 2097 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2098 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2174 \lstset{basicstyle=\linespread{0.9}\sf\small} 2175 \begin{tabular}{@{}l@{\hspace{0.5\parindentlnth}}l@{}} 2176 \multicolumn{1}{c@{\hspace{0.5\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2099 2177 \begin{cfa} 2100 2178 MIN 2101 2179 MAX 2102 M_PI2103 M_E2104 \end{cfa} 2105 & 2106 \begin{cfa} 2107 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, 2108 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, 2109 M_PI, M_PIl , M_CPI, M_CPIl,2110 M_E, M_El , M_CE, M_CEl2180 PI 2181 E 2182 \end{cfa} 2183 & 2184 \begin{cfa} 2185 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN 2186 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX 2187 M_PI, M_PIl 2188 M_E, M_El 2111 2189 \end{cfa} 2112 2190 \end{tabular} … … 2117 2195 \subsection{Math} 2118 2196 2119 C library @math.h@ provides many mathematical routines.2120 \CFA routine overloading is used to condense these mathematical routines, \eg:2197 C library @math.h@ provides many mathematical functions. 2198 \CFA function overloading is used to condense these mathematical functions, \eg: 2121 2199 \begin{cquote} 2122 2200 \lstDeleteShortInline@% … … 2137 2215 \lstMakeShortInline@% 2138 2216 \end{cquote} 2139 The result is a significant reduction in names to access math routines, \eg:2217 The result is a significant reduction in names to access math functions, \eg: 2140 2218 \begin{cquote} 2141 2219 \lstDeleteShortInline@% … … 2156 2234 \lstMakeShortInline@% 2157 2235 \end{cquote} 2158 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 routinename with a single set of floating type(s).2236 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 function name with a single set of floating type(s). 2159 2237 For example, it is impossible to overload @atan@ for both one and two arguments; 2160 instead the names @atan@ and @atan2@ are required .2161 The key observation is that only a restricted set of type-generic macros are provided for a limited set of routinenames, which do not generalize across the type system, as in \CFA.2238 instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}). 2239 The key observation is that only a restricted set of type-generic macros are provided for a limited set of function names, which do not generalize across the type system, as in \CFA. 2162 2240 2163 2241 2164 2242 \subsection{Standard} 2165 2243 2166 C library @stdlib.h@ provides many general routines.2167 \CFA routine overloading is used to condense these utility routines, \eg:2244 C library @stdlib.h@ provides many general functions. 2245 \CFA function overloading is used to condense these utility functions, \eg: 2168 2246 \begin{cquote} 2169 2247 \lstDeleteShortInline@% … … 2184 2262 \lstMakeShortInline@% 2185 2263 \end{cquote} 2186 The result is a significant reduction in names to access utility routines, \eg:2264 The result is a significant reduction in names to access utility functions, \eg: 2187 2265 \begin{cquote} 2188 2266 \lstDeleteShortInline@% … … 2203 2281 \lstMakeShortInline@% 2204 2282 \end{cquote} 2205 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.2283 In additon, there are polymorphic functions, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@. 2206 2284 2207 2285 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety. … … 2220 2298 An array may be filled, resized, or aligned. 2221 2299 \end{description} 2222 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. 2223 2224 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2225 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety: 2226 \begin{cquote} 2227 \begin{cfa}[aboveskip=0pt] 2228 size_t dim = 10; $\C{// array dimension}$ 2229 char fill = '\xff'; $\C{// initialization fill value}$ 2230 int * ip; 2231 \end{cfa} 2232 \lstDeleteShortInline@% 2233 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2234 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2235 \begin{cfa} 2236 ip = alloc(); 2237 ip = alloc( fill ); 2238 ip = alloc( dim ); 2239 ip = alloc( dim, fill ); 2240 ip = alloc( ip, 2 * dim ); 2241 ip = alloc( ip, 4 * dim, fill ); 2242 2243 ip = align_alloc( 16 ); 2244 ip = align_alloc( 16, fill ); 2245 ip = align_alloc( 16, dim ); 2246 ip = align_alloc( 16, dim, fill ); 2247 \end{cfa} 2248 & 2249 \begin{cfa} 2250 ip = (int *)malloc( sizeof( int ) ); 2251 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2252 ip = (int *)malloc( dim * sizeof( int ) ); 2253 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2254 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2255 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2256 2257 ip = memalign( 16, sizeof( int ) ); 2258 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2259 ip = memalign( 16, dim * sizeof( int ) ); 2260 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2261 \end{cfa} 2262 \end{tabular} 2263 \lstMakeShortInline@% 2264 \end{cquote} 2265 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2266 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg: 2267 \begin{cfa} 2268 struct S { int i, j; }; 2269 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2270 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2271 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2272 \end{cfa} 2273 Note, \CC can only initialization array elements via the default constructor. 2274 2275 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. 2276 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2300 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-functions and how all the capabilities can be combined into two \CFA functions. 2301 \CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2302 Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety. 2277 2303 2278 2304 \begin{table} … … 2300 2326 \end{table} 2301 2327 2328 \begin{figure} 2329 \centering 2330 \begin{cquote} 2331 \begin{cfa}[aboveskip=0pt] 2332 size_t dim = 10; $\C{// array dimension}$ 2333 char fill = '\xff'; $\C{// initialization fill value}$ 2334 int * ip; 2335 \end{cfa} 2336 \lstDeleteShortInline@% 2337 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2338 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2339 \begin{cfa} 2340 ip = alloc(); 2341 ip = alloc( fill ); 2342 ip = alloc( dim ); 2343 ip = alloc( dim, fill ); 2344 ip = alloc( ip, 2 * dim ); 2345 ip = alloc( ip, 4 * dim, fill ); 2346 2347 ip = align_alloc( 16 ); 2348 ip = align_alloc( 16, fill ); 2349 ip = align_alloc( 16, dim ); 2350 ip = align_alloc( 16, dim, fill ); 2351 \end{cfa} 2352 & 2353 \begin{cfa} 2354 ip = (int *)malloc( sizeof( int ) ); 2355 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2356 ip = (int *)malloc( dim * sizeof( int ) ); 2357 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2358 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2359 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2360 2361 ip = memalign( 16, sizeof( int ) ); 2362 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2363 ip = memalign( 16, dim * sizeof( int ) ); 2364 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2365 \end{cfa} 2366 \end{tabular} 2367 \lstMakeShortInline@% 2368 \end{cquote} 2369 \caption{\CFA versus C Storage-Allocation} 2370 \label{f:StorageAllocation} 2371 \end{figure} 2372 2373 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2374 Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg: 2375 \begin{cfa} 2376 struct S { int i, j; }; 2377 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2378 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2379 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2380 \end{cfa} 2381 Note, \CC can only initialization array elements via the default constructor. 2382 2383 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. 2384 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2385 2302 2386 2303 2387 \subsection{I/O} … … 2387 2471 }% 2388 2472 \end{itemize} 2389 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.2473 There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output. 2390 2474 2391 2475 … … 2394 2478 2395 2479 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP. 2396 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.2480 The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers. 2397 2481 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@. 2398 2482 The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces. … … 2439 2523 Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks would show little runtime variance, other than in length and clarity of source code. 2440 2524 A more illustrative benchmark measures the costs of idiomatic usage of each language's features. 2441 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ routinesimilar to that in Section~\ref{sec:variadic-tuples}.2525 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ function similar to that in Section~\ref{sec:variadic-tuples}. 2442 2526 The benchmark test is similar for C and \CC. 2443 2527 The experiment uses element types @int@ and @pair(_Bool, char)@, and pushes $N=40M$ elements on a generic stack, copies the stack, clears one of the stacks, finds the maximum value in the other stack, and prints $N/2$ (to reduce graph height) constants. … … 2446 2530 \begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt] 2447 2531 int main( int argc, char * argv[] ) { 2448 FILE * out = fopen( "cfa-out.txt", "w" ); 2449 int maxi = 0, vali = 42; 2450 stack(int) si, ti; 2451 2452 REPEAT_TIMED( "push_int", N, push( &si, vali ); ) 2453 TIMED( "copy_int", ti = si; ) 2454 TIMED( "clear_int", clear( &si ); ) 2455 REPEAT_TIMED( "pop_int", N, 2456 int xi = pop( &ti ); if ( xi > maxi ) { maxi = xi; } ) 2457 REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); ) 2458 2459 pair(_Bool, char) maxp = { (_Bool)0, '\0' }, valp = { (_Bool)1, 'a' }; 2460 stack(pair(_Bool, char)) sp, tp; 2461 2462 REPEAT_TIMED( "push_pair", N, push( &sp, valp ); ) 2463 TIMED( "copy_pair", tp = sp; ) 2464 TIMED( "clear_pair", clear( &sp ); ) 2465 REPEAT_TIMED( "pop_pair", N, 2466 pair(_Bool, char) xp = pop( &tp ); if ( xp > maxp ) { maxp = xp; } ) 2467 REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); ) 2468 fclose(out); 2532 ofstream out = { "cfa-out.txt" }; 2533 int max = 0, val = 42; 2534 stack( int ) s, t; 2535 2536 REPEAT_TIMED( "push_int", N, push( s, val ); ) 2537 TIMED( "copy_int", t = s; ) 2538 TIMED( "clear_int", clear( s ); ) 2539 REPEAT_TIMED( "pop_int", N, int v = pop( t ); max = max( v, max ); ) 2540 REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; ) 2541 2542 pair( _Bool, char ) max = { false, '\0' }, val = { true, 'a' }; 2543 stack( pair( _Bool, char ) ) s, t; 2544 2545 REPEAT_TIMED( "push_pair", N, push( s, val ); ) 2546 TIMED( "copy_pair", t = s; ) 2547 TIMED( "clear_pair", clear( s ); ) 2548 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) v = pop( t ); max = max( v, max ); ) 2549 REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; ) 2469 2550 } 2470 2551 \end{cfa} … … 2537 2618 \CC is the most similar language to \CFA; 2538 2619 both are extensions to C with source and runtime backwards compatibility. 2539 The fundamental difference is in their engineering approach toC compatibility and programmer expectation.2540 While \CC provides good backwardscompatibility with C, it has a steep learning curve for many of its extensions.2620 The fundamental difference is the engineering approach to maintain C compatibility and programmer expectation. 2621 While \CC provides good compatibility with C, it has a steep learning curve for many of its extensions. 2541 2622 For example, polymorphism is provided via three disjoint mechanisms: overloading, inheritance, and templates. 2542 2623 The overloading is restricted because resolution does not use the return type, inheritance requires learning object-oriented programming and coping with a restricted nominal-inheritance hierarchy, templates cannot be separately compiled resulting in compilation/code bloat and poor error messages, and determining how these mechanisms interact and which to use is confusing. 2543 2624 In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate-compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm. 2544 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed properties for a type.2545 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function in codebeyond compilation errors during template expansion;2625 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties. 2626 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function beyond compilation errors during template expansion; 2546 2627 furthermore, \CC concepts are restricted to template polymorphism. 2547 2628 … … 2594 2675 2595 2676 2677 \subsection{Control Structures / Declarations / Literals} 2678 2679 2596 2680 \section{Conclusion and Future Work} 2597 2681 … … 2620 2704 2621 2705 The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, and Thierry Delisle on the features described in this paper, and thank Magnus Madsen for feedback in the writing. 2622 %This work is supported in part by a corporate partnership with \grantsponsor{Huawei}{Huawei Ltd.}{http://www.huawei.com}, and Aaron Moss and Peter Buhr are funded by the \grantsponsor{Natural Sciences and Engineering Research Council} of Canada. 2706 This work is supported through a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are funded by the Natural Sciences and Engineering Research Council of Canada. 2707 2623 2708 % the first author's \grantsponsor{NSERC-PGS}{NSERC PGS D}{http://www.nserc-crsng.gc.ca/Students-Etudiants/PG-CS/BellandPostgrad-BelletSuperieures_eng.asp} scholarship. 2624 2709 … … 2640 2725 \CFA 2641 2726 \begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt] 2727 forall(otype T) struct stack_node; 2728 forall(otype T) struct stack { 2729 stack_node(T) * head; 2730 }; 2642 2731 forall(otype T) struct stack_node { 2643 2732 T value; 2644 2733 stack_node(T) * next; 2645 2734 }; 2646 forall(otype T) void ?{}( stack(T) * s) { (&s->head){ 0 }; }2647 forall(otype T) void ?{}( stack(T) * s, stack(T) t) {2648 stack_node(T) ** crnt = &s ->head;2735 forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; } 2736 forall(otype T) void ?{}( stack(T) & s, stack(T) t ) { 2737 stack_node(T) ** crnt = &s.head; 2649 2738 for ( stack_node(T) * next = t.head; next; next = next->next ) { 2650 *crnt = ((stack_node(T) *)malloc()){ next->value }; /***/ 2739 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2740 (*new_node){ next->value }; /***/ 2741 *crnt = new_node; 2651 2742 stack_node(T) * acrnt = *crnt; 2652 2743 crnt = &acrnt->next; … … 2654 2745 *crnt = 0; 2655 2746 } 2656 forall(otype T) stack(T) ?=?( stack(T) * s, stack(T) t) {2657 if ( s ->head == t.head ) return *s;2658 clear( s);2747 forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t ) { 2748 if ( s.head == t.head ) return s; 2749 clear( s ); 2659 2750 s{ t }; 2660 return *s; 2661 } 2662 forall(otype T) void ^?{}(stack(T) * s) { clear(s); } 2663 forall(otype T) _Bool empty(const stack(T) * s) { return s->head == 0; } 2664 forall(otype T) void push(stack(T) * s, T value) { 2665 s->head = ((stack_node(T) *)malloc()){ value, s->head }; /***/ 2666 } 2667 forall(otype T) T pop(stack(T) * s) { 2668 stack_node(T) * n = s->head; 2669 s->head = n->next; 2670 T x = n->value; 2671 ^n{}; 2672 free(n); 2673 return x; 2674 } 2675 forall(otype T) void clear(stack(T) * s) { 2676 for ( stack_node(T) * next = s->head; next; ) { 2751 return s; 2752 } 2753 forall(otype T) void ^?{}( stack(T) & s) { clear( s ); } 2754 forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; } 2755 forall(otype T) void push( stack(T) & s, T value ) { 2756 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2757 (*new_node){ value, s.head }; /***/ 2758 s.head = new_node; 2759 } 2760 forall(otype T) T pop( stack(T) & s ) { 2761 stack_node(T) * n = s.head; 2762 s.head = n->next; 2763 T v = n->value; 2764 delete( n ); 2765 return v; 2766 } 2767 forall(otype T) void clear( stack(T) & s ) { 2768 for ( stack_node(T) * next = s.head; next; ) { 2677 2769 stack_node(T) * crnt = next; 2678 2770 next = crnt->next; 2679 delete( crnt);2771 delete( crnt ); 2680 2772 } 2681 s ->head = 0;2773 s.head = 0; 2682 2774 } 2683 2775 \end{cfa} … … 2827 2919 2828 2920 2829 \begin{comment}2830 2831 \subsubsection{bench.h}2832 (\texttt{bench.hpp} is similar.)2833 2834 \lstinputlisting{evaluation/bench.h}2835 2836 \subsection{C}2837 2838 \subsubsection{c-stack.h} ~2839 2840 \lstinputlisting{evaluation/c-stack.h}2841 2842 \subsubsection{c-stack.c} ~2843 2844 \lstinputlisting{evaluation/c-stack.c}2845 2846 \subsubsection{c-pair.h} ~2847 2848 \lstinputlisting{evaluation/c-pair.h}2849 2850 \subsubsection{c-pair.c} ~2851 2852 \lstinputlisting{evaluation/c-pair.c}2853 2854 \subsubsection{c-print.h} ~2855 2856 \lstinputlisting{evaluation/c-print.h}2857 2858 \subsubsection{c-print.c} ~2859 2860 \lstinputlisting{evaluation/c-print.c}2861 2862 \subsubsection{c-bench.c} ~2863 2864 \lstinputlisting{evaluation/c-bench.c}2865 2866 \subsection{\CFA}2867 2868 \subsubsection{cfa-stack.h} ~2869 2870 \lstinputlisting{evaluation/cfa-stack.h}2871 2872 \subsubsection{cfa-stack.c} ~2873 2874 \lstinputlisting{evaluation/cfa-stack.c}2875 2876 \subsubsection{cfa-print.h} ~2877 2878 \lstinputlisting{evaluation/cfa-print.h}2879 2880 \subsubsection{cfa-print.c} ~2881 2882 \lstinputlisting{evaluation/cfa-print.c}2883 2884 \subsubsection{cfa-bench.c} ~2885 2886 \lstinputlisting{evaluation/cfa-bench.c}2887 2888 \subsection{\CC}2889 2890 \subsubsection{cpp-stack.hpp} ~2891 2892 \lstinputlisting[language=c++]{evaluation/cpp-stack.hpp}2893 2894 \subsubsection{cpp-print.hpp} ~2895 2896 \lstinputlisting[language=c++]{evaluation/cpp-print.hpp}2897 2898 \subsubsection{cpp-bench.cpp} ~2899 2900 \lstinputlisting[language=c++]{evaluation/cpp-bench.cpp}2901 2902 \subsection{\CCV}2903 2904 \subsubsection{object.hpp} ~2905 2906 \lstinputlisting[language=c++]{evaluation/object.hpp}2907 2908 \subsubsection{cpp-vstack.hpp} ~2909 2910 \lstinputlisting[language=c++]{evaluation/cpp-vstack.hpp}2911 2912 \subsubsection{cpp-vstack.cpp} ~2913 2914 \lstinputlisting[language=c++]{evaluation/cpp-vstack.cpp}2915 2916 \subsubsection{cpp-vprint.hpp} ~2917 2918 \lstinputlisting[language=c++]{evaluation/cpp-vprint.hpp}2919 2920 \subsubsection{cpp-vbench.cpp} ~2921 2922 \lstinputlisting[language=c++]{evaluation/cpp-vbench.cpp}2923 \end{comment}2924 2925 2921 \end{document} 2926 2922 -
doc/papers/general/evaluation/cfa-bench.c
r094476d rcaa649b 1 #include <stdio.h> 1 #include <fstream> 2 #include <stdlib> 3 #include <stdbool.h> 2 4 #include "bench.h" 3 5 #include "cfa-stack.h" … … 5 7 #include "cfa-print.h" 6 8 7 int main( int argc, char * argv[] ) {8 FILE * out = fopen( "/dev/null", "w" );9 int max i = 0, vali= 42;10 stack( int) si, ti;9 int main( int argc, char * argv[] ) { 10 ofstream out = { "/dev/null" }; 11 int max = 0, val = 42; 12 stack( int ) s, t; 11 13 12 REPEAT_TIMED( "push_int", N, push( &si, vali ); ) 13 TIMED( "copy_int", ti = si; ) 14 TIMED( "clear_int", clear( &si ); ) 15 REPEAT_TIMED( "pop_int", N, 16 int xi = pop( &ti ); 17 if ( xi > maxi ) { maxi = xi; } ) 18 REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); ) 14 REPEAT_TIMED( "push_int", N, push( s, val ); ) 15 TIMED( "copy_int", t = s; ) 16 TIMED( "clear_int", clear( s ); ) 17 REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); ) 18 REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; ) 19 19 20 pair( _Bool, char) maxp = { (_Bool)0, '\0' }, valp = { (_Bool)1, 'a' };21 stack( pair(_Bool, char)) sp, tp;20 pair( _Bool, char ) max = { (_Bool)false, '\0' }, val = { (_Bool)true, 'a' }; 21 stack( pair( _Bool, char ) ) s, t; 22 22 23 REPEAT_TIMED( "push_pair", N, push( &sp, valp ); ) 24 TIMED( "copy_pair", tp = sp; ) 25 TIMED( "clear_pair", clear( &sp ); ) 26 REPEAT_TIMED( "pop_pair", N, 27 pair(_Bool, char) xp = pop( &tp ); 28 if ( xp > maxp ) { maxp = xp; } ) 29 REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); ) 30 fclose(out); 23 REPEAT_TIMED( "push_pair", N, push( s, val ); ) 24 TIMED( "copy_pair", t = s; ) 25 TIMED( "clear_pair", clear( s ); ) 26 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); ) 27 REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; ) 31 28 } -
doc/papers/general/evaluation/cfa-pair.c
r094476d rcaa649b 1 1 #include "cfa-pair.h" 2 #include "fstream" 2 3 3 forall(otype R, otype S 4 forall(otype R, otype S 4 5 | { int ?==?(R, R); int ?<?(R, R); int ?<?(S, S); }) 5 6 int ?<?(pair(R, S) p, pair(R, S) q) { … … 7 8 } 8 9 9 forall(otype R, otype S 10 forall(otype R, otype S 10 11 | { int ?==?(R, R); int ?<?(R, R); int ?<=?(S, S); }) 11 12 int ?<=?(pair(R, S) p, pair(R, S) q) { … … 23 24 } 24 25 25 forall(otype R, otype S 26 forall(otype R, otype S 26 27 | { int ?==?(R, R); int ?>?(R, R); int ?>?(S, S); }) 27 28 int ?>?(pair(R, S) p, pair(R, S) q) { … … 29 30 } 30 31 31 forall(otype R, otype S 32 forall(otype R, otype S 32 33 | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); }) 33 34 int ?>=?(pair(R, S) p, pair(R, S) q) { 34 35 return p.first > q.first || ( p.first == q.first && p.second >= q.second ); 35 36 } 37 38 forall(otype R, otype S) 39 forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S ); }) 40 ostype & ?|?( ostype & os, pair(R, S) p ) { 41 return os | '[' | p.first | ',' | p.second | ']'; 42 } // ?|? -
doc/papers/general/evaluation/cfa-pair.h
r094476d rcaa649b 1 1 #pragma once 2 3 #include "iostream" 2 4 3 5 forall(otype R, otype S) struct pair { … … 27 29 | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); }) 28 30 int ?>=?(pair(R, S) p, pair(R, S) q); 31 32 forall(otype R, otype S) 33 forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, pair(R, S) ); }) 34 ostype & ?|?( ostype & os, pair(R, S) ); -
doc/papers/general/evaluation/cfa-stack.c
r094476d rcaa649b 4 4 forall(otype T) struct stack_node { 5 5 T value; 6 stack_node(T) * next;6 stack_node(T) * next; 7 7 }; 8 forall(otype T) void ?{}( stack_node(T) & node, T value, stack_node(T) * next ) { 9 node.value = value; 10 node.next = next; 11 } 8 12 9 forall(otype T) void ?{}( stack(T)* s) { (&s->head){ 0 }; }13 forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; } 10 14 11 forall(otype T) void ?{}(stack(T)* s, stack(T) t) { 12 stack_node(T)** crnt = &s->head; 13 for ( stack_node(T)* next = t.head; next; next = next->next ) { 14 *crnt = ((stack_node(T)*)malloc()){ next->value }; /***/ 15 stack_node(T)* acrnt = *crnt; 15 forall(otype T) void ?{}( stack(T) & s, stack(T) t ) { 16 stack_node(T) ** crnt = &s.head; 17 for ( stack_node(T) * next = t.head; next; next = next->next ) { 18 // *crnt = new( next->value, 0 ); 19 stack_node(T)* new_node = ((stack_node(T)*)malloc()); 20 (*new_node){ next->value }; /***/ 21 *crnt = new_node; 22 stack_node(T) * acrnt = *crnt; 16 23 crnt = &acrnt->next; 17 24 } … … 19 26 } 20 27 21 forall(otype T) stack(T) ?=?( stack(T)* s, stack(T) t) {22 if ( s ->head == t.head ) return *s;23 clear( s);28 forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t ) { 29 if ( s.head == t.head ) return s; 30 clear( s ); 24 31 s{ t }; 25 return *s;32 return s; 26 33 } 27 34 28 forall(otype T) void ^?{}( stack(T)* s) { clear(s); }35 forall(otype T) void ^?{}( stack(T) & s) { clear( s ); } 29 36 30 forall(otype T) _Bool empty( const stack(T)* s) { return s->head == 0; }37 forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; } 31 38 32 forall(otype T) void push(stack(T)* s, T value) { 33 s->head = ((stack_node(T)*)malloc()){ value, s->head }; /***/ 39 forall(otype T) void push( stack(T) & s, T value ) { 40 // s.head = new( value, s.head ); 41 stack_node(T)* new_node = ((stack_node(T)*)malloc()); 42 (*new_node){ value, s.head }; /***/ 43 s.head = new_node; 34 44 } 35 45 36 forall(otype T) T pop(stack(T)* s) { 37 stack_node(T)* n = s->head; 38 s->head = n->next; 39 T x = n->value; 40 ^n{}; 41 free(n); 42 return x; 46 forall(otype T) T pop( stack(T) & s ) { 47 stack_node(T) * n = s.head; 48 s.head = n->next; 49 T v = n->value; 50 delete( n ); 51 return v; 43 52 } 44 53 45 forall(otype T) void clear( stack(T)* s) {46 for ( stack_node(T)* next = s->head; next; ) {47 stack_node(T) * crnt = next;54 forall(otype T) void clear( stack(T) & s ) { 55 for ( stack_node(T) * next = s.head; next; ) { 56 stack_node(T) * crnt = next; 48 57 next = crnt->next; 49 delete( crnt);58 delete( crnt ); 50 59 } 51 s ->head = 0;60 s.head = 0; 52 61 } -
doc/papers/general/evaluation/cfa-stack.h
r094476d rcaa649b 3 3 forall(otype T) struct stack_node; 4 4 forall(otype T) struct stack { 5 stack_node(T) * head;5 stack_node(T) * head; 6 6 }; 7 7 8 forall(otype T) void ?{}( stack(T)* s);9 forall(otype T) void ?{}( stack(T)* s, stack(T) t);10 forall(otype T) stack(T) ?=?( stack(T)* s, stack(T) t);11 forall(otype T) void ^?{}( stack(T)*s);8 forall(otype T) void ?{}( stack(T) & s ); 9 forall(otype T) void ?{}( stack(T) & s, stack(T) t ); 10 forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t ); 11 forall(otype T) void ^?{}( stack(T) & s); 12 12 13 forall(otype T) _Bool empty( const stack(T)* s);14 forall(otype T) void push( stack(T)* s, T value);15 forall(otype T) T pop( stack(T)* s);16 forall(otype T) void clear( stack(T)* s);13 forall(otype T) _Bool empty( const stack(T) & s ); 14 forall(otype T) void push( stack(T) & s, T value ); 15 forall(otype T) T pop( stack(T) & s ); 16 forall(otype T) void clear( stack(T) & s ); -
src/Common/PassVisitor.impl.h
r094476d rcaa649b 2277 2277 } 2278 2278 2279 2279 //-------------------------------------------------------------------------- 2280 // TupleType 2280 2281 template< typename pass_type > 2281 2282 void PassVisitor< pass_type >::visit( TupleType * node ) { 2282 VISIT_BODY( node ); 2283 } 2284 2283 VISIT_START( node ); 2284 2285 maybeAccept_impl( node->forall, *this ); 2286 maybeAccept_impl( node->types, *this ); 2287 maybeAccept_impl( node->members, *this ); 2288 2289 VISIT_END( node ); 2290 } 2291 2292 template< typename pass_type > 2293 Type * PassVisitor< pass_type >::mutate( TupleType * node ) { 2294 MUTATE_START( node ); 2295 2296 maybeMutate_impl( node->forall, *this ); 2297 maybeMutate_impl( node->types, *this ); 2298 maybeMutate_impl( node->members, *this ); 2299 2300 MUTATE_END( Type, node ); 2301 } 2302 2303 //-------------------------------------------------------------------------- 2304 // TypeofType 2285 2305 template< typename pass_type > 2286 2306 void PassVisitor< pass_type >::visit( TypeofType * node ) { 2287 VISIT_BODY( node ); 2288 } 2289 2307 VISIT_START( node ); 2308 2309 assert( node->expr ); 2310 maybeAccept_impl( node->expr, *this ); 2311 2312 VISIT_END( node ); 2313 } 2314 2315 template< typename pass_type > 2316 Type * PassVisitor< pass_type >::mutate( TypeofType * node ) { 2317 MUTATE_START( node ); 2318 2319 assert( node->expr ); 2320 maybeMutate_impl( node->expr, *this ); 2321 2322 MUTATE_END( Type, node ); 2323 } 2324 2325 //-------------------------------------------------------------------------- 2326 // AttrType 2290 2327 template< typename pass_type > 2291 2328 void PassVisitor< pass_type >::visit( AttrType * node ) { 2292 VISIT_BODY( node ); 2293 } 2294 2329 VISIT_START( node ); 2330 2331 if ( node->isType ) { 2332 assert( node->type ); 2333 maybeAccept_impl( node->type, *this ); 2334 } else { 2335 assert( node->expr ); 2336 maybeAccept_impl( node->expr, *this ); 2337 } // if 2338 2339 VISIT_END( node ); 2340 } 2341 2342 template< typename pass_type > 2343 Type * PassVisitor< pass_type >::mutate( AttrType * node ) { 2344 MUTATE_START( node ); 2345 2346 if ( node->isType ) { 2347 assert( node->type ); 2348 maybeMutate_impl( node->type, *this ); 2349 } else { 2350 assert( node->expr ); 2351 maybeMutate_impl( node->expr, *this ); 2352 } // if 2353 2354 MUTATE_END( Type, node ); 2355 } 2356 2357 //-------------------------------------------------------------------------- 2358 // VarArgsType 2295 2359 template< typename pass_type > 2296 2360 void PassVisitor< pass_type >::visit( VarArgsType * node ) { 2297 VISIT_BODY( node ); 2298 } 2299 2361 VISIT_START( node ); 2362 2363 maybeAccept_impl( node->forall, *this ); 2364 2365 VISIT_END( node ); 2366 } 2367 2368 template< typename pass_type > 2369 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) { 2370 MUTATE_START( node ); 2371 2372 maybeMutate_impl( node->forall, *this ); 2373 2374 MUTATE_END( Type, node ); 2375 } 2376 2377 //-------------------------------------------------------------------------- 2378 // ZeroType 2300 2379 template< typename pass_type > 2301 2380 void PassVisitor< pass_type >::visit( ZeroType * node ) { 2302 VISIT_BODY( node ); 2303 } 2304 2381 VISIT_START( node ); 2382 2383 maybeAccept_impl( node->forall, *this ); 2384 2385 VISIT_END( node ); 2386 } 2387 2388 template< typename pass_type > 2389 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) { 2390 MUTATE_START( node ); 2391 2392 maybeMutate_impl( node->forall, *this ); 2393 2394 MUTATE_END( Type, node ); 2395 } 2396 2397 //-------------------------------------------------------------------------- 2398 // OneType 2305 2399 template< typename pass_type > 2306 2400 void PassVisitor< pass_type >::visit( OneType * node ) { 2307 VISIT_BODY( node ); 2308 } 2309 2401 VISIT_START( node ); 2402 2403 maybeAccept_impl( node->forall, *this ); 2404 2405 VISIT_END( node ); 2406 } 2407 2408 template< typename pass_type > 2409 Type * PassVisitor< pass_type >::mutate( OneType * node ) { 2410 MUTATE_START( node ); 2411 2412 maybeMutate_impl( node->forall, *this ); 2413 2414 MUTATE_END( Type, node ); 2415 } 2416 2417 //-------------------------------------------------------------------------- 2418 // Designation 2310 2419 template< typename pass_type > 2311 2420 void PassVisitor< pass_type >::visit( Designation * node ) { 2312 2421 VISIT_START( node ); 2313 2422 2314 maybeAccept_impl( node-> get_designators(), *this );2423 maybeAccept_impl( node->designators, *this ); 2315 2424 2316 2425 VISIT_END( node ); … … 2321 2430 MUTATE_START( node ); 2322 2431 2323 maybeMutate_impl( node-> get_designators(), *this );2432 maybeMutate_impl( node->designators, *this ); 2324 2433 2325 2434 MUTATE_END( Designation, node ); … … 2332 2441 VISIT_START( node ); 2333 2442 2334 visitExpression( node-> get_value());2443 visitExpression( node->value ); 2335 2444 2336 2445 VISIT_END( node ); … … 2341 2450 MUTATE_START( node ); 2342 2451 2343 node-> set_value( mutateExpression( node->get_value() ));2452 node->value = mutateExpression( node->value ); 2344 2453 2345 2454 MUTATE_END( Initializer, node ); 2346 2455 } 2347 2456 2457 //-------------------------------------------------------------------------- 2458 // ListInit 2348 2459 template< typename pass_type > 2349 2460 void PassVisitor< pass_type >::visit( ListInit * node ) { 2350 VISIT_BODY( node ); 2351 } 2352 2461 VISIT_START( node ); 2462 2463 maybeAccept_impl( node->designations, *this ); 2464 maybeAccept_impl( node->initializers, *this ); 2465 2466 VISIT_END( node ); 2467 } 2468 2469 template< typename pass_type > 2470 Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) { 2471 MUTATE_START( node ); 2472 2473 maybeMutate_impl( node->designations, *this ); 2474 maybeMutate_impl( node->initializers, *this ); 2475 2476 MUTATE_END( Initializer, node ); 2477 } 2478 2479 //-------------------------------------------------------------------------- 2480 // ConstructorInit 2353 2481 template< typename pass_type > 2354 2482 void PassVisitor< pass_type >::visit( ConstructorInit * node ) { 2355 VISIT_BODY( node ); 2356 } 2357 2483 VISIT_START( node ); 2484 2485 maybeAccept_impl( node->ctor, *this ); 2486 maybeAccept_impl( node->dtor, *this ); 2487 maybeAccept_impl( node->init, *this ); 2488 2489 VISIT_END( node ); 2490 } 2491 2492 template< typename pass_type > 2493 Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) { 2494 MUTATE_START( node ); 2495 2496 maybeMutate_impl( node->ctor, *this ); 2497 maybeMutate_impl( node->dtor, *this ); 2498 maybeMutate_impl( node->init, *this ); 2499 2500 MUTATE_END( Initializer, node ); 2501 } 2502 2503 //-------------------------------------------------------------------------- 2504 // Subrange 2358 2505 template< typename pass_type > 2359 2506 void PassVisitor< pass_type >::visit( Subrange * node ) { 2360 VISIT_BODY( node ); 2361 } 2362 2507 VISIT_START( node ); 2508 2509 VISIT_END( node ); 2510 } 2511 2512 template< typename pass_type > 2513 Subrange * PassVisitor< pass_type >::mutate( Subrange * node ) { 2514 MUTATE_START( node ); 2515 2516 MUTATE_END( Subrange, node ); 2517 } 2518 2519 //-------------------------------------------------------------------------- 2520 // Attribute 2363 2521 template< typename pass_type > 2364 2522 void PassVisitor< pass_type >::visit( Constant * node ) { 2365 VISIT_BODY( node ); 2366 } 2367 2523 VISIT_START( node ); 2524 2525 VISIT_END( node ); 2526 } 2527 2528 template< typename pass_type > 2529 Constant * PassVisitor< pass_type >::mutate( Constant * node ) { 2530 MUTATE_START( node ); 2531 2532 MUTATE_END( Constant, node ); 2533 } 2534 2535 //-------------------------------------------------------------------------- 2536 // Attribute 2368 2537 template< typename pass_type > 2369 2538 void PassVisitor< pass_type >::visit( Attribute * node ) { 2370 VISIT_BODY( node ); 2371 } 2372 2373 //--------------------------------------------------------------------------------------------------------------- 2374 2375 template< typename pass_type > 2376 Type * PassVisitor< pass_type >::mutate( TupleType * node ) { 2377 MUTATE_BODY( Type, node ); 2378 } 2379 2380 template< typename pass_type > 2381 Type * PassVisitor< pass_type >::mutate( TypeofType * node ) { 2382 MUTATE_BODY( Type, node ); 2383 } 2384 2385 template< typename pass_type > 2386 Type * PassVisitor< pass_type >::mutate( AttrType * node ) { 2387 MUTATE_BODY( Type, node ); 2388 } 2389 2390 template< typename pass_type > 2391 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) { 2392 MUTATE_BODY( Type, node ); 2393 } 2394 2395 template< typename pass_type > 2396 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) { 2397 MUTATE_BODY( Type, node ); 2398 } 2399 2400 template< typename pass_type > 2401 Type * PassVisitor< pass_type >::mutate( OneType * node ) { 2402 MUTATE_BODY( Type, node ); 2403 } 2404 2405 template< typename pass_type > 2406 Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) { 2407 MUTATE_BODY( Initializer, node ); 2408 } 2409 2410 template< typename pass_type > 2411 Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) { 2412 MUTATE_BODY( Initializer, node ); 2413 } 2414 2415 template< typename pass_type > 2416 Subrange * PassVisitor< pass_type >::mutate( Subrange * node ) { 2417 MUTATE_BODY( Subrange, node ); 2418 } 2419 2420 template< typename pass_type > 2421 Constant * PassVisitor< pass_type >::mutate( Constant * node ) { 2422 MUTATE_BODY( Constant, node ); 2539 VISIT_START( node ); 2540 2541 maybeAccept_impl( node->parameters, *this ); 2542 2543 VISIT_END( node ); 2423 2544 } 2424 2545 2425 2546 template< typename pass_type > 2426 2547 Attribute * PassVisitor< pass_type >::mutate( Attribute * node ) { 2427 MUTATE_BODY( Attribute, node ); 2428 } 2429 2548 MUTATE_START( node ); 2549 2550 maybeMutate_impl( node->parameters, *this ); 2551 2552 MUTATE_END( Attribute, node ); 2553 } 2554 2555 //-------------------------------------------------------------------------- 2556 // TypeSubstitution 2430 2557 template< typename pass_type > 2431 2558 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) { -
src/Common/SemanticError.cc
r094476d rcaa649b 14 14 // 15 15 16 #include <cstdarg> 16 17 #include <cstdio> // for fileno, stderr 17 18 #include <unistd.h> // for isatty … … 50 51 } 51 52 52 void SemanticWarningImpl( CodeLocation location, std::string msg ) { 53 namespace { 54 // convert format string and arguments into a single string 55 std::string fmtToString(const char * fmt, va_list ap) { 56 int size = 128; 57 while ( true ) { 58 char buf[size]; 59 va_list args; 60 va_copy( args, ap ); 61 int n = vsnprintf(&buf[0], size, fmt, args); 62 va_end( args ); 63 if ( n < size && n >= 0 ) return buf; 64 size *= 2; 65 } 66 assert( false ); 67 } 68 } 69 70 void SemanticWarningImpl( CodeLocation location, Warning, const char * const fmt, ... ) { 71 va_list args; 72 va_start(args, fmt); 73 std::string msg = fmtToString( fmt, args ); 74 va_end(args); 53 75 std::cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << std::endl; 54 76 } -
src/Common/SemanticError.h
r094476d rcaa649b 37 37 38 38 constexpr const char * const WarningFormats[] = { 39 39 "self assignment of expression: %s", 40 40 }; 41 41 42 42 enum class Warning { 43 SelfAssignment, 43 44 NUMBER_OF_WARNINGS, //This MUST be the last warning 44 45 }; … … 49 50 ); 50 51 51 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[ id], __VA_ARGS__)52 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id], __VA_ARGS__) 52 53 53 54 void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4))); … … 71 72 } 72 73 73 74 75 76 74 // Local Variables: // 77 75 // tab-width: 4 // -
src/Common/utility.h
r094476d rcaa649b 162 162 } 163 163 164 #define toCString( ... ) toString( __VA_ARGS__ ).c_str() 165 164 166 // replace element of list with all elements of another list 165 167 template< typename T > -
src/GenPoly/Specialize.cc
r094476d rcaa649b 200 200 } 201 201 202 struct EnvTrimmer {203 TypeSubstitution * env, * newEnv;204 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}205 void previsit( TypeDecl * tyDecl ) {206 // transfer known bindings for seen type variables207 if ( Type * t = env->lookup( tyDecl->name ) ) {208 newEnv->add( tyDecl->name, t );209 }210 }211 };212 213 /// reduce environment to just the parts that are referenced in a given expression214 TypeSubstitution * trimEnv( ApplicationExpr * expr, TypeSubstitution * env ) {215 if ( env ) {216 TypeSubstitution * newEnv = new TypeSubstitution();217 PassVisitor<EnvTrimmer> trimmer( env, newEnv );218 expr->accept( trimmer );219 return newEnv;220 }221 return nullptr;222 }223 224 202 /// Generates a thunk that calls `actual` with type `funType` and returns its address 225 203 Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) { … … 265 243 } 266 244 267 appExpr-> set_env( trimEnv( appExpr, env ));245 appExpr->env = TypeSubstitution::newFromExpr( appExpr, env ); 268 246 if ( inferParams ) { 269 247 appExpr->get_inferParams() = *inferParams; -
src/InitTweak/FixInit.cc
r094476d rcaa649b 68 68 typedef std::unordered_map< int, int > UnqCount; 69 69 70 struct SelfAssignChecker { 71 void previsit( ApplicationExpr * appExpr ); 72 }; 73 70 74 struct InsertImplicitCalls : public WithTypeSubstitution { 71 75 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 183 187 }; 184 188 185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {189 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution { 186 190 public: 187 191 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 235 239 236 240 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 241 PassVisitor<SelfAssignChecker> checker; 242 acceptAll( translationUnit, checker ); 243 237 244 // fixes ConstructorInit for global variables. should happen before fixInitializers. 238 245 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); … … 311 318 } 312 319 320 namespace { 321 // Relatively simple structural comparison for expressions, needed to determine 322 // if two expressions are "the same" (used to determine if self assignment occurs) 323 struct StructuralChecker { 324 Expression * stripCasts( Expression * expr ) { 325 // this might be too permissive. It's possible that only particular casts are relevant. 326 while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) { 327 expr = cast->arg; 328 } 329 return expr; 330 } 331 332 void previsit( Expression * ) { 333 // anything else does not qualify 334 isSimilar = false; 335 } 336 337 template<typename T> 338 T * cast( Expression * node ) { 339 // all expressions need to ignore casts, so this bit has been factored out 340 return dynamic_cast< T * >( stripCasts( node ) ); 341 } 342 343 // ignore casts 344 void previsit( CastExpr * ) {} 345 346 void previsit( MemberExpr * memExpr ) { 347 if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) { 348 if ( otherMember->member == memExpr->member ) { 349 other = otherMember->aggregate; 350 return; 351 } 352 } 353 isSimilar = false; 354 } 355 356 void previsit( VariableExpr * varExpr ) { 357 if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) { 358 if ( otherVar->var == varExpr->var ) { 359 return; 360 } 361 } 362 isSimilar = false; 363 } 364 365 void previsit( AddressExpr * ) { 366 if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) { 367 other = addrExpr->arg; 368 return; 369 } 370 isSimilar = false; 371 } 372 373 Expression * other = nullptr; 374 bool isSimilar = true; 375 }; 376 377 bool structurallySimilar( Expression * e1, Expression * e2 ) { 378 PassVisitor<StructuralChecker> checker; 379 checker.pass.other = e2; 380 e1->accept( checker ); 381 return checker.pass.isSimilar; 382 } 383 } 384 385 void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) { 386 DeclarationWithType * function = getFunction( appExpr ); 387 if ( isAssignment( function ) ) { 388 if ( appExpr->args.size() == 2 ) { 389 // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits) 390 if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) { 391 SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) ); 392 } 393 } 394 } 395 } 396 313 397 Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) { 314 398 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { … … 364 448 ResolvExpr::findVoidExpression( resolved, indexer ); 365 449 assert( resolved ); 366 if ( resolved-> get_env()) {450 if ( resolved->env ) { 367 451 // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes. 368 env->add( *resolved-> get_env());369 delete resolved-> get_env();370 resolved-> set_env( nullptr );452 env->add( *resolved->env ); 453 delete resolved->env; 454 resolved->env = nullptr; 371 455 } // if 372 456 delete stmt; … … 550 634 // add destructors after current statement 551 635 for ( Expression * dtor : dtors ) { 636 // take relevant bindings from environment 637 assert( ! dtor->env ); 638 dtor->env = maybeClone( env ); 552 639 stmtsToAddAfter.push_back( new ExprStmt( dtor ) ); 553 640 } // for -
src/Makefile.in
r094476d rcaa649b 247 247 SynTree/driver_cfa_cpp-TypeDecl.$(OBJEXT) \ 248 248 SynTree/driver_cfa_cpp-Initializer.$(OBJEXT) \ 249 SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \250 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \251 249 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \ 252 250 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \ … … 527 525 SynTree/FunctionDecl.cc SynTree/AggregateDecl.cc \ 528 526 SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \ 529 SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \ 530 SynTree/TypeSubstitution.cc SynTree/Attribute.cc \ 531 SynTree/VarExprReplacer.cc Tuples/TupleAssignment.cc \ 532 Tuples/TupleExpansion.cc Tuples/Explode.cc \ 533 Virtual/ExpandCasts.cc 527 SynTree/Initializer.cc SynTree/TypeSubstitution.cc \ 528 SynTree/Attribute.cc SynTree/VarExprReplacer.cc \ 529 Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \ 530 Tuples/Explode.cc Virtual/ExpandCasts.cc 534 531 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \ 535 532 ${cfa_cpplib_PROGRAMS}} … … 911 908 SynTree/driver_cfa_cpp-Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \ 912 909 SynTree/$(DEPDIR)/$(am__dirstamp) 913 SynTree/driver_cfa_cpp-Visitor.$(OBJEXT): SynTree/$(am__dirstamp) \914 SynTree/$(DEPDIR)/$(am__dirstamp)915 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \916 SynTree/$(DEPDIR)/$(am__dirstamp)917 910 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT): \ 918 911 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) … … 1053 1046 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Po@am__quote@ 1054 1047 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Po@am__quote@ 1055 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po@am__quote@1056 1048 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Po@am__quote@ 1057 1049 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Po@am__quote@ … … 1069 1061 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po@am__quote@ 1070 1062 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po@am__quote@ 1071 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po@am__quote@1072 1063 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@ 1073 1064 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po@am__quote@ … … 2478 2469 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2479 2470 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Initializer.obj `if test -f 'SynTree/Initializer.cc'; then $(CYGPATH_W) 'SynTree/Initializer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Initializer.cc'; fi` 2480 2481 SynTree/driver_cfa_cpp-Visitor.o: SynTree/Visitor.cc2482 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Visitor.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo -c -o SynTree/driver_cfa_cpp-Visitor.o `test -f 'SynTree/Visitor.cc' || echo '$(srcdir)/'`SynTree/Visitor.cc2483 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po2484 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/Visitor.cc' object='SynTree/driver_cfa_cpp-Visitor.o' libtool=no @AMDEPBACKSLASH@2485 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@2486 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Visitor.o `test -f 'SynTree/Visitor.cc' || echo '$(srcdir)/'`SynTree/Visitor.cc2487 2488 SynTree/driver_cfa_cpp-Visitor.obj: SynTree/Visitor.cc2489 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Visitor.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo -c -o SynTree/driver_cfa_cpp-Visitor.obj `if test -f 'SynTree/Visitor.cc'; then $(CYGPATH_W) 'SynTree/Visitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Visitor.cc'; fi`2490 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po2491 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/Visitor.cc' object='SynTree/driver_cfa_cpp-Visitor.obj' libtool=no @AMDEPBACKSLASH@2492 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@2493 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Visitor.obj `if test -f 'SynTree/Visitor.cc'; then $(CYGPATH_W) 'SynTree/Visitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Visitor.cc'; fi`2494 2495 SynTree/driver_cfa_cpp-Mutator.o: SynTree/Mutator.cc2496 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Mutator.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo -c -o SynTree/driver_cfa_cpp-Mutator.o `test -f 'SynTree/Mutator.cc' || echo '$(srcdir)/'`SynTree/Mutator.cc2497 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po2498 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/Mutator.cc' object='SynTree/driver_cfa_cpp-Mutator.o' libtool=no @AMDEPBACKSLASH@2499 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@2500 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.o `test -f 'SynTree/Mutator.cc' || echo '$(srcdir)/'`SynTree/Mutator.cc2501 2502 SynTree/driver_cfa_cpp-Mutator.obj: SynTree/Mutator.cc2503 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Mutator.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`2504 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po2505 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/Mutator.cc' object='SynTree/driver_cfa_cpp-Mutator.obj' libtool=no @AMDEPBACKSLASH@2506 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@2507 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`2508 2471 2509 2472 SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc -
src/Parser/ExpressionNode.cc
r094476d rcaa649b 10 10 // Created On : Sat May 16 13:17:07 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Sep 27 22:51:55 201713 // Update Count : 7 8112 // Last Modified On : Sat Mar 3 18:22:33 2018 13 // Update Count : 796 14 14 // 15 15 … … 58 58 static inline bool checkD( char c ) { return c == 'd' || c == 'D'; } 59 59 static inline bool checkI( char c ) { return c == 'i' || c == 'I'; } 60 static inline bool checkB( char c ) { return c == 'b' || c == 'B'; } 60 61 static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } 61 62 … … 116 117 117 118 unsigned long long int v; // converted integral value 118 size_t last = str.length() - 1; // last characterof constant119 size_t last = str.length() - 1; // last subscript of constant 119 120 Expression * ret; 120 121 … … 129 130 } // if 130 131 131 if ( str[0] == '0' ) { // octal/hex constant ? 132 // Cannot be "0" 133 134 if ( str[0] == '0' ) { // radix character ? 132 135 dec = false; 133 if ( last != 0 && checkX( str[1] ) ) {// hex constant ?136 if ( checkX( str[1] ) ) { // hex constant ? 134 137 sscanf( (char *)str.c_str(), "%llx", &v ); 138 //printf( "%llx %llu\n", v, v ); 139 } else if ( checkB( str[1] ) ) { // binary constant ? 140 v = 0; 141 for ( unsigned int i = 2;; i += 1 ) { // compute value 142 if ( str[i] == '1' ) v |= 1; 143 if ( i == last ) break; 144 v <<= 1; 145 } // for 135 146 //printf( "%llx %llu\n", v, v ); 136 147 } else { // octal constant -
src/Parser/lex.ll
r094476d rcaa649b 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Thu Feb 22 18:11:27201813 * Update Count : 6 3712 * Last Modified On : Sat Mar 3 18:38:16 2018 13 * Update Count : 640 14 14 */ 15 15 … … 77 77 %} 78 78 79 binary [0-1] 79 80 octal [0-7] 80 81 nonzero [1-9] … … 103 104 nonzero_digits ({nonzero})|({nonzero}({decimal}|"_")*{decimal}) 104 105 decimal_constant {nonzero_digits}{integer_suffix_opt} 106 107 binary_digits ({binary})|({binary}({binary}|"_")*{binary}) 108 binary_prefix "0"[bB]"_"? 109 binary_constant {binary_prefix}{binary_digits}{integer_suffix_opt} 105 110 106 111 hex_digits ({hex})|({hex}({hex}|"_")*{hex}) … … 315 320 316 321 /* numeric constants */ 322 {binary_constant} { NUMERIC_RETURN(INTEGERconstant); } 323 {octal_constant} { NUMERIC_RETURN(INTEGERconstant); } 317 324 {decimal_constant} { NUMERIC_RETURN(INTEGERconstant); } 318 {octal_constant} { NUMERIC_RETURN(INTEGERconstant); }319 325 {hex_constant} { NUMERIC_RETURN(INTEGERconstant); } 320 326 {floating_decimal} { NUMERIC_RETURN(FLOATING_DECIMALconstant); } // must appear before floating_constant -
src/ResolvExpr/Resolver.cc
r094476d rcaa649b 788 788 stmtExpr->accept( resolver ); 789 789 stmtExpr->computeResult(); 790 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead? 790 791 } 791 792 … … 793 794 visit_children = false; 794 795 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit 795 maybeAccept( ctorInit-> get_ctor(), *visitor );796 maybeAccept( ctorInit-> get_dtor(), *visitor );796 maybeAccept( ctorInit->ctor, *visitor ); 797 maybeAccept( ctorInit->dtor, *visitor ); 797 798 798 799 // found a constructor - can get rid of C-style initializer 799 delete ctorInit-> get_init();800 ctorInit-> set_init( NULL );800 delete ctorInit->init; 801 ctorInit->init = nullptr; 801 802 802 803 // intrinsic single parameter constructors and destructors do nothing. Since this was 803 804 // implicitly generated, there's no way for it to have side effects, so get rid of it 804 805 // to clean up generated code. 805 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit-> get_ctor()) ) {806 delete ctorInit-> get_ctor();807 ctorInit-> set_ctor( NULL );808 } 809 810 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit-> get_dtor()) ) {811 delete ctorInit-> get_dtor();812 ctorInit-> set_dtor( NULL );806 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 807 delete ctorInit->ctor; 808 ctorInit->ctor = nullptr; 809 } 810 811 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 812 delete ctorInit->dtor; 813 ctorInit->dtor = nullptr; 813 814 } 814 815 -
src/ResolvExpr/TypeEnvironment.cc
r094476d rcaa649b 118 118 env.push_back( newClass ); 119 119 } // for 120 } 121 122 void TypeEnvironment::add( const TypeSubstitution & sub ) { 123 EqvClass newClass; 124 for ( auto p : sub ) { 125 newClass.vars.insert( p.first ); 126 newClass.type = p.second->clone(); 127 newClass.allowWidening = false; 128 // Minimal assumptions. Not technically correct, but might be good enough, and 129 // is the best we can do at the moment since information is lost in the 130 // transition to TypeSubstitution 131 newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false }; 132 add( newClass ); 133 } 120 134 } 121 135 -
src/ResolvExpr/TypeEnvironment.h
r094476d rcaa649b 76 76 void add( const EqvClass &eqvClass ); 77 77 void add( const Type::ForallList &tyDecls ); 78 void add( const TypeSubstitution & sub ); 78 79 template< typename SynTreeClass > int apply( SynTreeClass *&type ) const; 79 80 template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const; -
src/SynTree/Mutator.h
r094476d rcaa649b 22 22 class Mutator { 23 23 protected: 24 Mutator() ;25 virtual ~Mutator() ;24 Mutator() = default; 25 virtual ~Mutator() = default; 26 26 public: 27 27 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) = 0; -
src/SynTree/TypeSubstitution.cc
r094476d rcaa649b 104 104 bool TypeSubstitution::empty() const { 105 105 return typeEnv.empty() && varEnv.empty(); 106 } 107 108 namespace { 109 struct EnvTrimmer { 110 TypeSubstitution * env, * newEnv; 111 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 112 void previsit( TypeDecl * tyDecl ) { 113 // transfer known bindings for seen type variables 114 if ( Type * t = env->lookup( tyDecl->name ) ) { 115 newEnv->add( tyDecl->name, t ); 116 } 117 } 118 }; 119 } // namespace 120 121 /// reduce environment to just the parts that are referenced in a given expression 122 TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) { 123 if ( env ) { 124 TypeSubstitution * newEnv = new TypeSubstitution(); 125 PassVisitor<EnvTrimmer> trimmer( env, newEnv ); 126 expr->accept( trimmer ); 127 return newEnv; 128 } 129 return nullptr; 106 130 } 107 131 -
src/SynTree/TypeSubstitution.h
r094476d rcaa649b 55 55 void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result ); 56 56 57 /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr 58 static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env ); 59 57 60 void normalize(); 58 61 … … 79 82 TypeEnvType typeEnv; 80 83 VarEnvType varEnv; 84 85 public: 86 // has to come after declaration of typeEnv 87 auto begin() -> decltype( typeEnv.begin() ) { return typeEnv.begin(); } 88 auto end() -> decltype( typeEnv. end() ) { return typeEnv. end(); } 89 auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); } 90 auto end() const -> decltype( typeEnv. end() ) { return typeEnv. end(); } 81 91 }; 82 92 -
src/SynTree/Visitor.h
r094476d rcaa649b 21 21 class Visitor { 22 22 protected: 23 Visitor() ;24 virtual ~Visitor() ;23 Visitor() = default; 24 virtual ~Visitor() = default; 25 25 public: 26 26 // visit: Default implementation of all functions visits the children -
src/SynTree/module.mk
r094476d rcaa649b 46 46 SynTree/TypeDecl.cc \ 47 47 SynTree/Initializer.cc \ 48 SynTree/Visitor.cc \49 SynTree/Mutator.cc \50 48 SynTree/TypeSubstitution.cc \ 51 49 SynTree/Attribute.cc \ -
src/Tuples/TupleAssignment.cc
r094476d rcaa649b 281 281 } 282 282 283 // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator .283 // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator, and adds the bindings to the compositeEnv 284 284 // xxx - maybe this should happen in alternative finder for every StmtExpr? 285 // xxx - it's possible that these environments could contain some useful information. Maybe the right thing to do is aggregate the environments and pass the aggregate back to be added into the compositeEnv286 285 struct EnvRemover { 287 286 void previsit( ExprStmt * stmt ) { 288 delete stmt->expr->env; 289 stmt->expr->env = nullptr; 290 } 287 assert( compositeEnv ); 288 if ( stmt->expr->env ) { 289 compositeEnv->add( *stmt->expr->env ); 290 delete stmt->expr->env; 291 stmt->expr->env = nullptr; 292 } 293 } 294 295 ResolvExpr::TypeEnvironment * compositeEnv = nullptr; 291 296 }; 292 297 … … 300 305 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object 301 306 PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs 307 rm.pass.compositeEnv = &compositeEnv; 302 308 ctorInit->accept( rm ); 303 309 } -
src/libcfa/limits
r094476d rcaa649b 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 7 09:33:57 201713 // Update Count : 712 // Last Modified On : Thu Mar 1 16:20:54 2018 13 // Update Count : 13 14 14 // 15 15 … … 18 18 // Integral Constants 19 19 20 extern const signed char MIN; 21 extern const unsigned char MIN; 20 22 extern const short int MIN; 23 extern const unsigned short int MIN; 21 24 extern const int MIN; 25 extern const unsigned int MIN; 22 26 extern const long int MIN; 27 extern const unsigned long int MIN; 23 28 extern const long long int MIN; 29 extern const unsigned long long int MIN; 24 30 31 extern const signed char MAX; 32 extern const unsigned char MAX; 25 33 extern const short int MAX; 26 34 extern const unsigned short int MAX; … … 33 41 34 42 // Floating-Point Constants 43 44 extern const float MIN; 45 extern const double MIN; 46 extern const long double MIN; 47 extern const float _Complex MIN; 48 extern const double _Complex MIN; 49 extern const long double _Complex MIN; 50 51 extern const float MAX; 52 extern const double MAX; 53 extern const long double MAX; 54 extern const float _Complex MAX; 55 extern const double _Complex MAX; 56 extern const long double _Complex MAX; 35 57 36 58 extern const float PI; // pi … … 55 77 extern const long double _2_SQRT_PI; // 2 / sqrt(pi) 56 78 57 extern const _Complex PI;// pi58 extern const _Complex PI_2;// pi / 259 extern const _Complex PI_4;// pi / 460 extern const _Complex _1_PI;// 1 / pi61 extern const _Complex _2_PI;// 2 / pi62 extern const _Complex _2_SQRT_PI;// 2 / sqrt(pi)79 extern const float _Complex PI; // pi 80 extern const float _Complex PI_2; // pi / 2 81 extern const float _Complex PI_4; // pi / 4 82 extern const float _Complex _1_PI; // 1 / pi 83 extern const float _Complex _2_PI; // 2 / pi 84 extern const float _Complex _2_SQRT_PI; // 2 / sqrt(pi) 63 85 64 extern const long _Complex PI; // pi 65 extern const long _Complex PI_2; // pi / 2 66 extern const long _Complex PI_4; // pi / 4 67 extern const long _Complex _1_PI; // 1 / pi 68 extern const long _Complex _2_PI; // 2 / pi 69 extern const long _Complex _2_SQRT_PI; // 2 / sqrt(pi) 86 extern const double _Complex PI; // pi 87 extern const double _Complex PI_2; // pi / 2 88 extern const double _Complex PI_4; // pi / 4 89 extern const double _Complex _1_PI; // 1 / pi 90 extern const double _Complex _2_PI; // 2 / pi 91 extern const double _Complex _2_SQRT_PI; // 2 / sqrt(pi) 92 93 extern const long double _Complex PI; // pi 94 extern const long double _Complex PI_2; // pi / 2 95 extern const long double _Complex PI_4; // pi / 4 96 extern const long double _Complex _1_PI; // 1 / pi 97 extern const long double _Complex _2_PI; // 2 / pi 98 extern const long double _Complex _2_SQRT_PI; // 2 / sqrt(pi) 70 99 71 100 extern const float E; // e … … 93 122 extern const long double _1_SQRT_2; // 1/sqrt(2) 94 123 95 extern const _Complex E;// e96 extern const _Complex LOG2_E;// log_2(e)97 extern const _Complex LOG10_E;// log_10(e)98 extern const _Complex LN_2;// log_e(2)99 extern const _Complex LN_10;// log_e(10)100 extern const _Complex SQRT_2;// sqrt(2)101 extern const _Complex _1_SQRT_2;// 1 / sqrt(2)124 extern const float _Complex E; // e 125 extern const float _Complex LOG2_E; // log_2(e) 126 extern const float _Complex LOG10_E; // log_10(e) 127 extern const float _Complex LN_2; // log_e(2) 128 extern const float _Complex LN_10; // log_e(10) 129 extern const float _Complex SQRT_2; // sqrt(2) 130 extern const float _Complex _1_SQRT_2; // 1 / sqrt(2) 102 131 103 extern const long _Complex E; // e 104 extern const long _Complex LOG2_E; // log_2(e) 105 extern const long _Complex LOG10_E; // log_10(e) 106 extern const long _Complex LN_2; // log_e(2) 107 extern const long _Complex LN_10; // log_e(10) 108 extern const long _Complex SQRT_2; // sqrt(2) 109 extern const long _Complex _1_SQRT_2; // 1 / sqrt(2) 132 extern const double _Complex E; // e 133 extern const double _Complex LOG2_E; // log_2(e) 134 extern const double _Complex LOG10_E; // log_10(e) 135 extern const double _Complex LN_2; // log_e(2) 136 extern const double _Complex LN_10; // log_e(10) 137 extern const double _Complex SQRT_2; // sqrt(2) 138 extern const double _Complex _1_SQRT_2; // 1 / sqrt(2) 139 140 extern const long double _Complex E; // e 141 extern const long double _Complex LOG2_E; // log_2(e) 142 extern const long double _Complex LOG10_E; // log_10(e) 143 extern const long double _Complex LN_2; // log_e(2) 144 extern const long double _Complex LN_10; // log_e(10) 145 extern const long double _Complex SQRT_2; // sqrt(2) 146 extern const long double _Complex _1_SQRT_2; // 1 / sqrt(2) 110 147 111 148 // Local Variables: // -
src/libcfa/limits.c
r094476d rcaa649b 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 12 10:34:48 201613 // Update Count : 1712 // Last Modified On : Thu Mar 1 16:22:51 2018 13 // Update Count : 74 14 14 // 15 15 16 #include <limits.h> 17 #include <float.h> 18 #define __USE_GNU // get M_* constants 19 #include <math.h> 20 #include <complex.h> 16 21 #include "limits" 17 22 18 23 // Integral Constants 19 24 20 const short int MIN = -32768; 21 const int MIN = -2147483648; 22 #if __WORDSIZE == 64 23 const long int MIN = -9223372036854775807L - 1L; 24 #else 25 const long int MIN = (int)MIN; 26 #endif // M64 27 const long long int MIN = -9223372036854775807LL - 1LL; 25 const signed char MIN = SCHAR_MIN; 26 const unsigned char MIN = 0; 27 const short int MIN = SHRT_MIN; 28 const unsigned short int MIN = 0; 29 const int MIN = INT_MIN; 30 const unsigned int MIN = 0; 31 const long int MIN = LONG_MIN; 32 const unsigned long int MIN = 0; 33 const long long int MIN = LLONG_MIN; 34 const unsigned long long int MIN = 0; 28 35 29 const short int MAX = 32767; 30 const unsigned short int MAX = 65535; 31 const int MAX = 2147483647; 32 const unsigned int MAX = 4294967295_U; 33 #if __WORDSIZE == 64 34 const long int MAX = 9223372036854775807_L; 35 #else 36 const long int MAX = (int)MAX; 37 #endif // M64 38 const unsigned long int MAX = 4294967295_U; 39 const long long int MAX = 9223372036854775807_LL; 40 const unsigned long long int MAX = 18446744073709551615_ULL; 36 const signed char MAX = SCHAR_MAX; 37 const unsigned char MAX = UCHAR_MAX; 38 const short int MAX = SHRT_MAX; 39 const unsigned short int MAX = USHRT_MAX; 40 const int MAX = INT_MAX; 41 const unsigned int MAX = UINT_MAX; 42 const long int MAX = LONG_MAX; 43 const unsigned long int MAX = ULONG_MAX; 44 const long long int MAX = LLONG_MAX; 45 const unsigned long long int MAX = ULLONG_MAX; 41 46 42 47 // Floating-Point Constants 43 48 44 const float PI = 3.141592_F; // pi45 const float PI_2 = 1.570796_F; // pi / 246 const float PI_4 = 0.7853981_F; // pi / 447 const float _ 1_PI = 0.3183098_F; // 1 / pi48 const float _2_PI = 0.6366197_F; // 2 / pi49 const float _2_SQRT_PI = 1.128379_F; // 2 / sqrt(pi)49 const float MIN = FLT_MIN; 50 const double MIN = DBL_MIN; 51 const long double MIN = LDBL_MIN; 52 const float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I; 53 const double _Complex MIN = DBL_MIN + DBL_MIN * I; 54 const long double _Complex MIN = LDBL_MIN + LDBL_MIN * I; 50 55 51 const double PI = 3.14159265358979323846_D; // pi52 const double PI_2 = 1.57079632679489661923_D; // pi / 253 const double PI_4 = 0.78539816339744830962_D; // pi / 454 const double _1_PI = 0.31830988618379067154_D; // 1 / pi55 const double _ 2_PI = 0.63661977236758134308_D; // 2 / pi56 const double _2_SQRT_PI = 1.12837916709551257390_D; // 2 / sqrt(pi)56 const float MAX = FLT_MAX; 57 const double MAX = DBL_MAX; 58 const long double MAX = LDBL_MAX; 59 const float _Complex MAX = FLT_MAX + FLT_MAX * I; 60 const double _Complex MAX = DBL_MAX + DBL_MAX * I; 61 const long double _Complex MAX = LDBL_MAX + LDBL_MAX * I; 57 62 58 const long double PI = 3.1415926535897932384626433832795029_DL;// pi59 const long double PI_2 = 1.5707963267948966192313216916397514_DL;// pi / 260 const long double PI_4 = 0.7853981633974483096156608458198757_DL;// pi / 461 const long double _1_PI = 0.3183098861837906715377675267450287_DL;// 1 / pi62 const long double _2_PI = 0.6366197723675813430755350534900574_DL;// 2 / pi63 const long double _2_SQRT_PI = 1.1283791670955125738961589031215452_DL;// 2 / sqrt(pi)63 const float PI = (float)M_PI; // pi 64 const float PI_2 = (float)M_PI_2; // pi / 2 65 const float PI_4 = (float)M_PI_4; // pi / 4 66 const float _1_PI = (float)M_1_PI; // 1 / pi 67 const float _2_PI = (float)M_2_PI; // 2 / pi 68 const float _2_SQRT_PI = (float)M_2_SQRTPI; // 2 / sqrt(pi) 64 69 65 const double _Complex PI = 3.14159265358979323846_D+0.0_iD;// pi66 const double _Complex PI_2 = 1.57079632679489661923_D+0.0_iD;// pi / 267 const double _Complex PI_4 = 0.78539816339744830962_D+0.0_iD;// pi / 468 const double _ Complex _1_PI = 0.31830988618379067154_D+0.0_iD;// 1 / pi69 const double _ Complex _2_PI = 0.63661977236758134308_D+0.0_iD;// 2 / pi70 const double _ Complex _2_SQRT_PI = 1.12837916709551257390_D+0.0_iD;// 2 / sqrt(pi)70 const double PI = M_PI; // pi 71 const double PI_2 = M_PI_2; // pi / 2 72 const double PI_4 = M_PI_4; // pi / 4 73 const double _1_PI = M_1_PI; // 1 / pi 74 const double _2_PI = M_2_PI; // 2 / pi 75 const double _2_SQRT_PI = M_2_SQRTPI; // 2 / sqrt(pi) 71 76 72 const long double _Complex PI = 3.1415926535897932384626433832795029_L+0.0iL;// pi73 const long double _Complex PI_2 = 1.5707963267948966192313216916397514_L+0.0iL;// pi / 274 const long double _Complex PI_4 = 0.7853981633974483096156608458198757_L+0.0iL;// pi / 475 const long double _ Complex _1_PI = 0.3183098861837906715377675267450287_L+0.0iL;// 1 / pi76 const long double _ Complex _2_PI = 0.6366197723675813430755350534900574_L+0.0iL;// 2 / pi77 const long double _ Complex _2_SQRT_PI = 1.1283791670955125738961589031215452_L+0.0iL;// 2 / sqrt(pi)77 const long double PI = M_PIl; // pi 78 const long double PI_2 = M_PI_2l; // pi / 2 79 const long double PI_4 = M_PI_4l; // pi / 4 80 const long double _1_PI = M_1_PIl; // 1 / pi 81 const long double _2_PI = M_2_PIl; // 2 / pi 82 const long double _2_SQRT_PI = M_2_SQRTPIl; // 2 / sqrt(pi) 78 83 79 const float E = 2.718281; // e 80 const float LOG2_E = 1.442695; // log_2(e) 81 const float LOG10_E = 0.4342944; // log_10(e) 82 const float LN_2 = 0.6931471; // log_e(2) 83 const float LN_10 = 2.302585; // log_e(10) 84 const float SQRT_2 = 1.414213; // sqrt(2) 85 const float _1_SQRT_2 = 0.7071067; // 1 / sqrt(2) 84 const float _Complex PI = (float)M_PI + 0.0_iF; // pi 85 const float _Complex PI_2 = (float)M_PI_2 + 0.0_iF; // pi / 2 86 const float _Complex PI_4 = (float)M_PI_4 + 0.0_iF; // pi / 4 87 const float _Complex _1_PI = (float)M_1_PI + 0.0_iF; // 1 / pi 88 const float _Complex _2_PI = (float)M_2_PI + 0.0_iF; // 2 / pi 89 const float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi) 86 90 87 const double E = 2.7182818284590452354_D; // e 88 const double LOG2_E = 1.4426950408889634074_D; // log_2(e) 89 const double LOG10_E = 0.43429448190325182765_D; // log_10(e) 90 const double LN_2 = 0.69314718055994530942_D; // log_e(2) 91 const double LN_10 = 2.30258509299404568402_D; // log_e(10) 92 const double SQRT_2 = 1.41421356237309504880_D; // sqrt(2) 93 const double _1_SQRT_2 = 0.70710678118654752440_D; // 1 / sqrt(2) 91 const double _Complex PI = M_PI + 0.0_iD; // pi 92 const double _Complex PI_2 = M_PI_2 + 0.0_iD; // pi / 2 93 const double _Complex PI_4 = M_PI_4 + 0.0_iD; // pi / 4 94 const double _Complex _1_PI = M_1_PI + 0.0_iD; // 1 / pi 95 const double _Complex _2_PI = M_2_PI + 0.0_iD; // 2 / pi 96 const double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD; // 2 / sqrt(pi) 94 97 95 const long double E = 2.7182818284590452353602874713526625_DL; // e 96 const long double LOG2_E = 1.4426950408889634073599246810018921_DL; // log_2(e) 97 const long double LOG10_E = 0.4342944819032518276511289189166051_DL; // log_10(e) 98 const long double LN_2 = 0.6931471805599453094172321214581766_DL; // log_e(2) 99 const long double LN_10 = 2.3025850929940456840179914546843642_DL; // log_e(10) 100 const long double SQRT_2 = 1.4142135623730950488016887242096981_DL; // sqrt(2) 101 const long double _1_SQRT_2 = 0.7071067811865475244008443621048490_DL; // 1/sqrt(2) 98 const long double _Complex PI = M_PIl + 0.0_iL; // pi 99 const long double _Complex PI_2 = M_PI_2l + 0.0_iL; // pi / 2 100 const long double _Complex PI_4 = M_PI_4l + 0.0_iL; // pi / 4 101 const long double _Complex _1_PI = M_1_PIl + 0.0_iL; // 1 / pi 102 const long double _Complex _2_PI = M_2_PIl + 0.0_iL; // 2 / pi 103 const long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi) 102 104 103 const double _Complex E = 2.7182818284590452354_D+0.0_iD;// e104 const double _Complex LOG2_E = 1.4426950408889634074_D+0.0_iD;// log_2(e)105 const double _Complex LOG10_E = 0.43429448190325182765_D+0.0_iD;// log_10(e)106 const double _Complex LN_2 = 0.69314718055994530942_D+0.0_iD;// log_e(2)107 const double _Complex LN_10 = 2.30258509299404568402_D+0.0_iD;// log_e(10)108 const double _Complex SQRT_2 = 1.41421356237309504880_D+0.0_iD;// sqrt(2)109 const double _Complex _1_SQRT_2 = 0.70710678118654752440_D+0.0_iD;// 1 / sqrt(2)105 const float E = (float)M_E; // e 106 const float LOG2_E = (float)M_LOG2E; // log_2(e) 107 const float LOG10_E = (float)M_LOG10E; // log_10(e) 108 const float LN_2 = (float)M_LN2; // log_e(2) 109 const float LN_10 = (float)M_LN10; // log_e(10) 110 const float SQRT_2 = (float)M_SQRT2; // sqrt(2) 111 const float _1_SQRT_2 = (float)M_SQRT1_2; // 1 / sqrt(2) 110 112 111 const long double _Complex E = 2.7182818284590452353602874713526625_L+0.0_iL; // e 112 const long double _Complex LOG2_E = 1.4426950408889634073599246810018921_L+0.0_iL; // log_2(e) 113 const long double _Complex LOG10_E = 0.4342944819032518276511289189166051_L+0.0_iL; // log_10(e) 114 const long double _Complex LN_2 = 0.6931471805599453094172321214581766_L+0.0_iL; // log_e(2) 115 const long double _Complex LN_10 = 2.3025850929940456840179914546843642_L+0.0_iL; // log_e(10) 116 const long double _Complex SQRT_2 = 1.4142135623730950488016887242096981_L+0.0_iL; // sqrt(2) 117 const long double _Complex _1_SQRT_2 = 0.7071067811865475244008443621048490_L+0.0_iL; // 1 / sqrt(2) 113 const double E = M_E; // e 114 const double LOG2_E = M_LOG2E; // log_2(e) 115 const double LOG10_E = M_LOG10E; // log_10(e) 116 const double LN_2 = M_LN2; // log_e(2) 117 const double LN_10 = M_LN10; // log_e(10) 118 const double SQRT_2 = M_SQRT2; // sqrt(2) 119 const double _1_SQRT_2 = M_SQRT1_2; // 1 / sqrt(2) 120 121 const long double E = M_El; // e 122 const long double LOG2_E = M_LOG2El; // log_2(e) 123 const long double LOG10_E = M_LOG10El; // log_10(e) 124 const long double LN_2 = M_LN2l; // log_e(2) 125 const long double LN_10 = M_LN10l; // log_e(10) 126 const long double SQRT_2 = M_SQRT2l; // sqrt(2) 127 const long double _1_SQRT_2 = M_SQRT1_2l; // 1 / sqrt(2) 128 129 const float _Complex E = M_E + 0.0_iF; // e 130 const float _Complex LOG2_E = M_LOG2E + 0.0_iF; // log_2(e) 131 const float _Complex LOG10_E = M_LOG10E + 0.0_iF; // log_10(e) 132 const float _Complex LN_2 = M_LN2 + 0.0_iF; // log_e(2) 133 const float _Complex LN_10 = M_LN10 + 0.0_iF; // log_e(10) 134 const float _Complex SQRT_2 = M_SQRT2 + 0.0_iF; // sqrt(2) 135 const float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF; // 1 / sqrt(2) 136 137 const double _Complex E = M_E + 0.0_iD; // e 138 const double _Complex LOG2_E = M_LOG2E + 0.0_iD; // log_2(e) 139 const double _Complex LOG10_E = M_LOG10E + 0.0_iD; // log_10(e) 140 const double _Complex LN_2 = M_LN2 + 0.0_iD; // log_e(2) 141 const double _Complex LN_10 = M_LN10 + 0.0_iD; // log_e(10) 142 const double _Complex SQRT_2 = M_SQRT2 + 0.0_iD; // sqrt(2) 143 const double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD; // 1 / sqrt(2) 144 145 const long double _Complex E = M_El + 0.0_iL; // e 146 const long double _Complex LOG2_E = M_LOG2El + 0.0_iL; // log_2(e) 147 const long double _Complex LOG10_E = M_LOG10El + 0.0_iL; // log_10(e) 148 const long double _Complex LN_2 = M_LN2l + 0.0_iL; // log_e(2) 149 const long double _Complex LN_10 = M_LN10l + 0.0_iL; // log_e(10) 150 const long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL; // sqrt(2) 151 const long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL; // 1 / sqrt(2) 118 152 119 153 // Local Variables: // -
src/tests/.expect/KRfunctions.x86.txt
r094476d rcaa649b 82 82 signed int __a__i_2; 83 83 signed int __b__i_2; 84 signed int *(*_tmp_cp_ret 0)(signed int __x__i_1, signed int __y__i_1);85 ((void)(__x__PFPi_ii__2=(((void)(_tmp_cp_ret 0=__f10__FPFPi_ii__iPiPid__1(3, (&__a__i_2), (&__b__i_2), 3.5))) , _tmp_cp_ret0)));86 ((void)(_tmp_cp_ret 0) /* ^?{} */);84 signed int *(*_tmp_cp_ret2)(signed int __x__i_1, signed int __y__i_1); 85 ((void)(__x__PFPi_ii__2=(((void)(_tmp_cp_ret2=__f10__FPFPi_ii__iPiPid__1(3, (&__a__i_2), (&__b__i_2), 3.5))) , _tmp_cp_ret2))); 86 ((void)(_tmp_cp_ret2) /* ^?{} */); 87 87 const signed int __f1__FCi_iPiPi__2(signed int __a__i_2, signed int *__b__Pi_2, signed int *__c__Pi_2){ 88 88 __attribute__ ((unused)) const signed int ___retval_f1__Ci_2; -
src/tests/.expect/literals.x64.txt
r094476d rcaa649b 522 522 signed int __main__Fi___1(){ 523 523 __attribute__ ((unused)) signed int ___retval_main__i_1; 524 ((void)0b01101011); 525 ((void)0b01101011u); 526 ((void)0b01101011l); 527 ((void)0b01101011ll); 528 ((void)0b01101011ul); 529 ((void)0b01101011lu); 530 ((void)0b01101011ull); 531 ((void)0b01101011llu); 532 ((void)(+0b01101011)); 533 ((void)(+0b01101011u)); 534 ((void)(+0b01101011l)); 535 ((void)(+0b01101011ll)); 536 ((void)(+0b01101011ul)); 537 ((void)(+0b01101011lu)); 538 ((void)(+0b01101011ull)); 539 ((void)(+0b01101011llu)); 540 ((void)(-0b01101011)); 541 ((void)(-0b01101011u)); 542 ((void)(-0b01101011l)); 543 ((void)(-0b01101011ll)); 544 ((void)(-0b01101011ul)); 545 ((void)(-0b01101011lu)); 546 ((void)(-0b01101011ull)); 547 ((void)(-0b01101011llu)); 524 548 ((void)01234567); 525 549 ((void)01234567u); … … 1017 1041 ((void)(-0X0123456789.0123456789P-09F)); 1018 1042 ((void)(-0X0123456789.0123456789P-09L)); 1043 ((void)((signed char )0b01101011)); 1044 ((void)((signed short int )0b01101011)); 1045 ((void)((signed int )0b01101011)); 1046 ((void)((signed long int )0b01101011)); 1047 ((void)((__int128 )0b01101011)); 1048 ((void)((unsigned char )0b01101011u)); 1049 ((void)((signed short int )0b01101011u)); 1050 ((void)((unsigned int )0b01101011u)); 1051 ((void)((signed long int )0b01101011u)); 1052 ((void)((__int128 )0b01101011u)); 1053 ((void)(+((signed int )((signed char )0b01101011)))); 1054 ((void)(+((signed int )((signed short int )0b01101011)))); 1055 ((void)(+((signed int )0b01101011))); 1056 ((void)(+((signed long int )0b01101011))); 1057 ((void)(+((float )((__int128 )0b01101011)))); 1058 ((void)(+((signed int )((unsigned char )0b01101011u)))); 1059 ((void)(+((signed int )((signed short int )0b01101011u)))); 1060 ((void)(+((unsigned int )0b01101011u))); 1061 ((void)(+((signed long int )0b01101011u))); 1062 ((void)(+((float )((__int128 )0b01101011u)))); 1063 ((void)(-((signed int )((signed char )0b01101011)))); 1064 ((void)(-((signed int )((signed short int )0b01101011)))); 1065 ((void)(-((signed int )0b01101011))); 1066 ((void)(-((signed long int )0b01101011))); 1067 ((void)(-((float )((__int128 )0b01101011)))); 1068 ((void)(-((signed int )((unsigned char )0b01101011u)))); 1069 ((void)(-((signed int )((signed short int )0b01101011u)))); 1070 ((void)(-((unsigned int )0b01101011u))); 1071 ((void)(-((signed long int )0b01101011u))); 1072 ((void)(-((float )((__int128 )0b01101011u)))); 1019 1073 ((void)((signed char )01234567)); 1020 1074 ((void)((signed short int )01234567)); -
src/tests/.expect/user_literals.txt
r094476d rcaa649b 1 1 11.0714285714286 2 1 1.072252 15 3 3 11.0714285714286 4 24.8 5 11.248 4 6 11.0714285714286 5 11.0714285714286 6 22.0457142857143 7 28.0657142857143 7 8 secs 1 8 9 secs 23 -
src/tests/Makefile.am
r094476d rcaa649b 123 123 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 124 124 125 # Warnings 126 warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@ 127 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only -
src/tests/Makefile.in
r094476d rcaa649b 800 800 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 801 801 802 # Warnings 803 warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@ 804 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only 805 802 806 # Tell versions [3.59,3.63) of GNU make to not export all variables. 803 807 # Otherwise a system limit (for SysV at least) may be exceeded. -
src/tests/limits.c
r094476d rcaa649b 10 10 // Created On : Tue May 10 20:44:20 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue May 10 20:45:28 201613 // Update Count : 112 // Last Modified On : Thu Mar 1 16:21:55 2018 13 // Update Count : 7 14 14 // 15 15 … … 18 18 // Integral Constants 19 19 20 signed char m = MIN; 21 unsigned char m = MIN; 20 22 short int m = MIN; 23 unsigned short int m = MIN; 21 24 int m = MIN; 25 unsigned int m = MIN; 22 26 long int m = MIN; 27 unsigned long int m = MIN; 23 28 long long int m = MIN; 29 unsigned long long int m = MIN; 24 30 31 signed char M = MAX; 32 unsigned char M = MAX; 25 33 short int M = MAX; 26 34 unsigned short int M = MAX; … … 33 41 34 42 // Floating-Point Constants 43 44 float m = MIN; 45 double m = MIN; 46 long double m = MIN; 47 float _Complex m = MIN; 48 double _Complex m = MIN; 49 long double _Complex m = MIN; 50 51 float M = MAX; 52 double M = MAX; 53 long double M = MAX; 54 float _Complex M = MAX; 55 double _Complex M = MAX; 56 long double _Complex M = MAX; 35 57 36 58 float pi = PI; … … 55 77 long double _2_sqrt_pi = _2_SQRT_PI; 56 78 57 _Complex pi = PI;58 _Complex pi_2 = PI_2;59 _Complex pi_4 = PI_4;60 _Complex _1_pi = _1_PI;61 _Complex _2_pi = _2_PI;62 _Complex _2_sqrt_pi = _2_SQRT_PI;79 float _Complex pi = PI; 80 float _Complex pi_2 = PI_2; 81 float _Complex pi_4 = PI_4; 82 float _Complex _1_pi = _1_PI; 83 float _Complex _2_pi = _2_PI; 84 float _Complex _2_sqrt_pi = _2_SQRT_PI; 63 85 64 long _Complex pi = PI; 65 long _Complex pi_2 = PI_2; 66 long _Complex pi_4 = PI_4; 67 long _Complex _1_pi = _1_PI; 68 long _Complex _2_pi = _2_PI; 69 long _Complex _2_sqrt_pi = _2_SQRT_PI; 86 double _Complex pi = PI; 87 double _Complex pi_2 = PI_2; 88 double _Complex pi_4 = PI_4; 89 double _Complex _1_pi = _1_PI; 90 double _Complex _2_pi = _2_PI; 91 double _Complex _2_sqrt_pi = _2_SQRT_PI; 92 93 long double _Complex pi = PI; 94 long double _Complex pi_2 = PI_2; 95 long double _Complex pi_4 = PI_4; 96 long double _Complex _1_pi = _1_PI; 97 long double _Complex _2_pi = _2_PI; 98 long double _Complex _2_sqrt_pi = _2_SQRT_PI; 70 99 71 100 float e = E; … … 93 122 long double _1_sqrt_2 = _1_SQRT_2; 94 123 95 _Complex e = E;96 _Complex log2_e = LOG2_E;97 _Complex log10_e = LOG10_E;98 _Complex ln_2 = LN_2;99 _Complex ln_10 = LN_10;100 _Complex sqrt_2 = SQRT_2;101 _Complex _1_sqrt_2 = _1_SQRT_2;124 float _Complex e = E; 125 float _Complex log2_e = LOG2_E; 126 float _Complex log10_e = LOG10_E; 127 float _Complex ln_2 = LN_2; 128 float _Complex ln_10 = LN_10; 129 float _Complex sqrt_2 = SQRT_2; 130 float _Complex _1_sqrt_2 = _1_SQRT_2; 102 131 103 long _Complex e = E; 104 long _Complex log2_e = LOG2_E; 105 long _Complex log10_e = LOG10_E; 106 long _Complex ln_2 = LN_2; 107 long _Complex ln_10 = LN_10; 108 long _Complex sqrt_2 = SQRT_2; 109 long _Complex _1_sqrt_2 = _1_SQRT_2; 132 double _Complex e = E; 133 double _Complex log2_e = LOG2_E; 134 double _Complex log10_e = LOG10_E; 135 double _Complex ln_2 = LN_2; 136 double _Complex ln_10 = LN_10; 137 double _Complex sqrt_2 = SQRT_2; 138 double _Complex _1_sqrt_2 = _1_SQRT_2; 139 140 long double _Complex e = E; 141 long double _Complex log2_e = LOG2_E; 142 long double _Complex log10_e = LOG10_E; 143 long double _Complex ln_2 = LN_2; 144 long double _Complex ln_10 = LN_10; 145 long double _Complex sqrt_2 = SQRT_2; 146 long double _Complex _1_sqrt_2 = _1_SQRT_2; 110 147 111 148 int main(int argc, char const *argv[]) { -
src/tests/literals.c
r094476d rcaa649b 10 10 // Created On : Sat Sep 9 16:34:38 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 25 20:26:00 201713 // Update Count : 13 212 // Last Modified On : Sun Mar 4 10:41:31 2018 13 // Update Count : 134 14 14 // 15 15 … … 31 31 // integer literals 32 32 33 // binary 34 0b01101011; 0b01101011u; 0b01101011l; 0b01101011ll; 0b01101011ul; 0b01101011lu; 0b01101011ull; 0b01101011llu; 35 +0b01101011; +0b01101011u; +0b01101011l; +0b01101011ll; +0b01101011ul; +0b01101011lu; +0b01101011ull; +0b01101011llu; 36 -0b01101011; -0b01101011u; -0b01101011l; -0b01101011ll; -0b01101011ul; -0b01101011lu; -0b01101011ull; -0b01101011llu; 37 33 38 // octal 34 39 01234567; 01234567u; 01234567l; 01234567ll; 01234567ul; 01234567lu; 01234567ull; 01234567llu; … … 148 153 #ifdef __CFA__ 149 154 // fixed-size length 155 156 // binary 157 0b01101011_l8; 0b01101011_l16; 0b01101011_l32; 0b01101011_l64; 0b01101011_l128; 0b01101011_l8u; 0b01101011_ul16; 0b01101011_l32u; 0b01101011_ul64; 0b01101011_ul128; 158 +0b01101011_l8; +0b01101011_l16; +0b01101011_l32; +0b01101011_l64; +0b01101011_l128; +0b01101011_l8u; +0b01101011_ul16; +0b01101011_l32u; +0b01101011_ul64; +0b01101011_ul128; 159 -0b01101011_l8; -0b01101011_l16; -0b01101011_l32; -0b01101011_l64; -0b01101011_l128; -0b01101011_l8u; -0b01101011_ul16; -0b01101011_l32u; -0b01101011_ul64; -0b01101011_ul128; 150 160 151 161 // octal -
src/tests/user_literals.c
r094476d rcaa649b 10 10 // Created On : Wed Sep 6 21:40:50 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 7 09:12:36 201713 // Update Count : 5 012 // Last Modified On : Sun Mar 4 11:14:02 2018 13 // Update Count : 52 14 14 // 15 15 … … 31 31 32 32 33 struct Weight { 34 double stones; 35 }; 36 void ?{}( Weight & w ) { w.stones = 0; } // operations 33 struct Weight { double stones; }; 34 void ?{}( Weight & w ) { w.stones = 0; } 37 35 void ?{}( Weight & w, double w ) { w.stones = w; } 38 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } 36 Weight ?+?( Weight l, Weight r ) { 37 return (Weight){ l.stones + r.stones }; 38 } 39 39 ofstream & ?|?( ofstream & os, Weight w ) { return os | w.stones; } 40 40 41 41 Weight ?`st( double w ) { return (Weight){ w }; } // backquote for user literals 42 42 Weight ?`lb( double w ) { return (Weight){ w / 14.0 }; } 43 Weight ?`kg( double w ) { return (Weight) { w * 0.1575}; } 44 43 Weight ?`kg( double w ) { return (Weight) { w * 0.16 }; } 45 44 46 45 int main() { 47 Weight w, hw = { 14 }; // 14 stone 48 w = 11`st + 1`lb; 46 Weight w, heavy = { 20 }; // 20 stone 47 w = 155`lb; 48 sout | w | endl; 49 w = 0b_1111`st; 50 sout | w | endl; 51 w = 0_233`lb; // octal weight (155) 52 sout | w | endl; 53 w = 0x_9b_u`kg; 49 54 sout | w | endl; 50 55 w = 70.3`kg; 51 56 sout | w | endl; 52 w = 1 55`lb;57 w = 11`st + 1`lb; 53 58 sout | w | endl; 54 w = 0x_9b_u`lb; // hexadecimal unsigned weight (155) 55 sout | w | endl; 56 w = 0_233`lb; // octal weight (155) 57 sout | w | endl; 58 w = 5`st + 8`kg + 25`lb + hw; 59 w = 5`st + 8`kg + 25`lb + heavy; 59 60 sout | w | endl; 60 61
Note: See TracChangeset
for help on using the changeset viewer.