Changeset f4abc58
- Timestamp:
- Mar 7, 2018, 5:09:18 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:
- fb11446e
- Parents:
- b2e8841 (diff), 7b0dfa4 (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:
-
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/bibliography/pl.bib
rb2e8841 rf4abc58 1439 1439 contributer = {pabuhr@plg}, 1440 1440 author = {Peter A. Buhr}, 1441 title = {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 6.1.0},1441 title = {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 7.0.0}, 1442 1442 institution = {School of Computer Science, University of Waterloo}, 1443 1443 address = {Waterloo, Ontario, Canada, N2L 3G1}, 1444 month = jul,1445 year = 201 5,1446 note = {\href{http://plg.uwaterloo.ca/~usystem/pub/uSystem/u++- 6.1.0.sh}{http://\-plg.\-uwaterloo.\-ca/\-$\sim$usystem/\-pub/\-uSystem/\-u++-6.1.0.sh}},1444 month = dec, 1445 year = 2017, 1446 note = {\href{http://plg.uwaterloo.ca/~usystem/pub/uSystem/u++-7.0.0.sh}{http://\-plg.\-uwaterloo.\-ca/\-$\sim$usystem/\-pub/\-uSystem/\-u++-7.0.0.sh}}, 1447 1447 } 1448 1448 -
doc/papers/general/Paper.tex
rb2e8841 rf4abc58 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} … … 56 58 \setlength{\parindentlnth}{\parindent} 57 59 60 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{\lst@basicstyle{#1}}}} 58 61 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}} 59 62 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} … … 229 232 All of the features discussed in this paper are working, unless a feature states it is a future feature for completion. 230 233 234 Finally, it is impossible to describe a programming language without usages before definitions. 235 Therefore, syntax and semantics appear before explanations; 236 hence, patience is necessary until details are presented. 237 231 238 232 239 \section{Polymorphic Functions} … … 261 268 \end{cfa} 262 269 \CFA maximizes the ability to reuse names to aggressively address the naming problem. 263 In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction for a programmer.270 In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction. 264 271 In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum. 265 272 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). 266 273 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. 267 274 268 \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. 269 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@. 270 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. 271 Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA implements @_Generic@ for backwards-compatibility purposes. \TODO{actually implement that} 275 \Celeven added @_Generic@ expressions, which is used in preprocessor macros to provide a form of ad-hoc polymorphism; 276 however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading. 277 The macro wrapping the generic expression imposes some limitations; 278 \eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@. 279 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 dispatch functions, which must all have distinct names. 280 For backwards compatibility, \CFA supports @_Generic@ expressions, but it is an unnecessary mechanism. \TODO{actually implement that} 272 281 273 282 % http://fanf.livejournal.com/144696.html … … 284 293 int forty_two = identity( 42 ); $\C{// T is bound to int, forty\_two == 42}$ 285 294 \end{cfa} 286 Th e @identity@ function abovecan be applied to any complete \newterm{object type} (or @otype@).295 This @identity@ function can be applied to any complete \newterm{object type} (or @otype@). 287 296 The type variable @T@ is transformed into a set of additional implicit parameters encoding sufficient information about @T@ to create and return a variable of that type. 288 297 The \CFA implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor and destructor. 289 298 If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@). 290 299 291 In \CFA, the polymorphi sm runtime-cost is spread over each polymorphic call, due to passing more argumentsto polymorphic functions;300 In \CFA, the polymorphic runtime-cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions; 292 301 the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual-function calls. 293 302 A design advantage is that, unlike \CC template-functions, \CFA polymorphic-functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat. … … 301 310 which works for any type @T@ with a matching addition operator. 302 311 The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@. 303 There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} ,in its type analysis.312 There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis. 304 313 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an eager conversion to @int@. 305 314 \CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition. … … 310 319 \begin{cfa} 311 320 void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, 312 int (* compar)( const void *, const void * )); 313 314 int comp( const void * t1, const void * t2 ) { return *(double *)t1 < *(double *)t2 ? -1 : 315 *(double *)t2 < *(double *)t1 ? 1 : 0; } 316 321 int (* compar)( const void *, const void * )); 322 int comp( const void * t1, const void * t2 ) { 323 return *(double *)t1 < *(double *)t2 ? -1 : *(double *)t2 < *(double *)t1 ? 1 : 0; 324 } 317 325 double key = 5.0, vals[10] = { /* 10 sorted float values */ }; 318 326 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$ … … 322 330 forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) { 323 331 int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ } 324 return (T *)bsearch( &key, arr, size, sizeof(T), comp ); }325 332 return (T *)bsearch( &key, arr, size, sizeof(T), comp ); 333 } 326 334 forall( otype T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) { 327 335 T * result = bsearch( key, arr, size ); $\C{// call first version}$ 328 return result ? result - arr : size; }$\C{// pointer subtraction includes sizeof(T)}$329 336 return result ? result - arr : size; $\C{// pointer subtraction includes sizeof(T)}$ 337 } 330 338 double * val = bsearch( 5.0, vals, 10 ); $\C{// selection based on return type}$ 331 339 int posn = bsearch( 5.0, vals, 10 ); … … 334 342 Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope. 335 343 As well, an alternate kind of return is made available: position versus pointer to found element. 336 \CC's type-system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a template d@bsearch@.344 \CC's type-system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a template @bsearch@. 337 345 338 346 \CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations (see Section~\ref{sec:libraries}). … … 380 388 \begin{cfa} 381 389 trait otype( dtype T | sized(T) ) { // sized is a pseudo-trait for types with known size and alignment 382 void ?{}( T *); $\C{// default constructor}$383 void ?{}( T *, T ); $\C{// copy constructor}$384 void ?=?( T *, T ); $\C{// assignment operator}$385 void ^?{}( T *); }; $\C{// destructor}$390 void ?{}( T & ); $\C{// default constructor}$ 391 void ?{}( T &, T ); $\C{// copy constructor}$ 392 void ?=?( T &, T ); $\C{// assignment operator}$ 393 void ^?{}( T & ); }; $\C{// destructor}$ 386 394 \end{cfa} 387 395 Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete type: stack-allocatable, default or copy-initialized, assigned, and deleted. … … 427 435 One approach is to write bespoke data-structures for each context in which they are needed. 428 436 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. 429 A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allow sreuse of code with common functionality.437 A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allow reuse of code with common functionality. 430 438 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. 431 439 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. 432 Furthermore, writing and using preprocessor macros can beunnatural and inflexible.440 Furthermore, writing and using preprocessor macros is unnatural and inflexible. 433 441 434 442 \CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data-types. … … 442 450 S second; 443 451 }; 444 forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; } 445 forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; } 446 447 pair( const char *, int ) p = { "magic", 42 }; 452 forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; } $\C{// dynamic}$ 453 forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; } $\C{// dtype-static (concrete)}$ 454 455 pair( const char *, int ) p = { "magic", 42 }; $\C{// concrete}$ 448 456 int i = value( p ); 449 pair( void *, int * ) q = { 0, &p.second }; 457 pair( void *, int * ) q = { 0, &p.second }; $\C{// concrete}$ 450 458 i = value( q ); 451 459 double d = 1.0; 452 pair( double *, double * ) r = { &d, &d }; 460 pair( double *, double * ) r = { &d, &d }; $\C{// concrete}$ 453 461 d = value( r ); 454 462 \end{cfa} … … 456 464 \CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}. 457 465 Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters. 458 A type may have polymorphic parameters but still be concrete, called \newterm{dtype-static}.466 A \newterm{dtype-static} type has polymorphic parameters but is still concrete. 459 467 Polymorphic pointers are an example of dtype-static types, \eg @forall(dtype T) T *@ is a polymorphic type, but for any @T@, @T *@ is a fixed-sized pointer, and therefore, can be represented by a @void *@ in code generation. 460 468 … … 473 481 For example, the concrete instantiation for @pair( const char *, int )@ is: 474 482 \begin{cfa} 475 struct _pair_conc 1{483 struct _pair_conc0 { 476 484 const char * first; 477 485 int second; … … 480 488 481 489 A concrete generic-type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations. 482 In the above example, the @pair( F *, T * )@ parameter to @value _p@ is such a type; its expansion is below and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate:483 \begin{cfa} 484 struct _pair_conc 0{490 In the above example, the @pair( F *, T * )@ parameter to @value@ is such a type; its expansion is below and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate: 491 \begin{cfa} 492 struct _pair_conc1 { 485 493 void * first; 486 494 void * second; … … 494 502 As mentioned in Section~\ref{sec:poly-fns}, @otype@ function parameters (in fact all @sized@ polymorphic parameters) come with implicit size and alignment parameters provided by the caller. 495 503 Dynamic generic-types also have an \newterm{offset array} containing structure-member offsets. 496 A dynamic generic- unionneeds no such offset array, as all members are at offset 0, but size and alignment are still necessary.504 A dynamic generic-@union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary. 497 505 Access to members of a dynamic structure is provided at runtime via base-displacement addressing with the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime. 498 506 499 507 The offset arrays are statically generated where possible. 500 508 If a dynamic generic-type is declared to be passed or returned by value from a polymorphic function, the translator can safely assume the generic type is complete (\ie has a known layout) at any call-site, and the offset array is passed from the caller; 501 if the generic type is concrete at the call site, the elements of this offset array can even be statically generated using the C @offsetof@ macro. 502 As an example, @p.second@ in the @value@ function above is implemented as @*(p + _offsetof_pair[1])@, where @p@ is a @void *@, and @_offsetof_pair@ is the offset array passed into @value@ for @pair( const char *, T )@. 503 The offset array @_offsetof_pair@ is generated at the call site as @size_t _offsetof_pair[] = { offsetof(_pair_conc1, first), offsetof(_pair_conc1, second) }@. 509 if the generic type is concrete at the call site, the elements of this offset array can even be statically generated using the C @offsetof@ macro. 510 As an example, the body of the second @value@ function is implemented like this: 511 \begin{cfa} 512 _assign_T(_retval, p + _offsetof_pair[1]); $\C{// return *p.second}$ 513 \end{cfa} 514 @_assign_T@ is passed in as an implicit parameter from @otype T@, and takes two @T*@ (@void*@ in the generated code), a destination and a source; @_retval@ is the pointer to a caller-allocated buffer for the return value, the usual \CFA method to handle dynamically-sized return types. 515 @_offsetof_pair@ is the offset array passed into @value@; this array is generated at the call site as: 516 \begin{cfa} 517 size_t _offsetof_pair[] = { offsetof(_pair_conc0, first), offsetof(_pair_conc0, second) } 518 \end{cfa} 504 519 505 520 In some cases the offset arrays cannot be statically generated. … … 584 599 \subsection{Tuple Expressions} 585 600 586 The addition of multiple-return-value functions (MRVF) are uselesswithout a syntax for accepting multiple values at the call-site.601 The addition of multiple-return-value functions (MRVF) are \emph{useless} without a syntax for accepting multiple values at the call-site. 587 602 The simplest mechanism for capturing the return values is variable assignment, allowing the values to be retrieved directly. 588 603 As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions (as above), called a \newterm{tuple}. … … 820 835 \end{cfa} 821 836 so the thunk provides flattening and structuring conversions to inferred functions, improving the compatibility of tuples and polymorphism. 822 These thunks take advantage of gcc C nested-functions to produce closures that have the usual function-pointer signature .837 These thunks take advantage of gcc C nested-functions to produce closures that have the usual function-pointer signature WHAT DOES THIS MEAN???. 823 838 824 839 … … 876 891 print(arg); print(rest); 877 892 } 878 void print( c har * x ) { printf( "%s", x ); }893 void print( const char * x ) { printf( "%s", x ); } 879 894 void print( int x ) { printf( "%d", x ); } 880 895 void print( S s ) { print( "{ ", s.x, ",", s.y, " }" ); } … … 885 900 The polymorphic @print@ allows printing any list of types, where as each individual type has a @print@ function. 886 901 The individual print functions can be used to build up more complicated @print@ functions, such as @S@, which cannot be done with @printf@ in C. 902 This mechanism is used to seamlessly print tuples in the \CFA I/O library (see Section~\ref{s:IOLibrary}). 887 903 888 904 Finally, it is possible to use @ttype@ polymorphism to provide arbitrary argument forwarding functions. … … 988 1004 \section{Control Structures} 989 1005 990 \CFA identifies missing and problematic control structures in C, and extends and modifies these control structures to increase functionality and safety. 1006 \CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds to control structures to increase functionality and safety. 1007 1008 1009 \subsection{\texorpdfstring{\LstKeywordStyle{if} Statement}{if Statement}} 1010 1011 The @if@ expression allows declarations, similar to @for@ declaration expression: 1012 \begin{cfa} 1013 if ( int x = f() ) ... $\C{// x != 0}$ 1014 if ( int x = f(), y = g() ) ... $\C{// x != 0 \&\& y != 0}$ 1015 if ( int x = f(), y = g(); `x < y` ) ... $\C{// relational expression}$ 1016 \end{cfa} 1017 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.} 1018 The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses. 1019 1020 1021 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 1022 1023 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. 1024 1025 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.}. 1026 \CFA provides a shorthand for a non-contiguous list: 1027 \begin{cquote} 1028 \lstDeleteShortInline@% 1029 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1030 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1031 \begin{cfa} 1032 case 2, 10, 34, 42: 1033 \end{cfa} 1034 & 1035 \begin{cfa} 1036 case 2: case 10: case 34: case 42: 1037 \end{cfa} 1038 \end{tabular} 1039 \lstMakeShortInline@% 1040 \end{cquote} 1041 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1042 \begin{cquote} 1043 \lstDeleteShortInline@% 1044 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1045 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1046 \begin{cfa} 1047 case 2~42: 1048 \end{cfa} 1049 & 1050 \begin{cfa} 1051 case 2: case 3: ... case 41: case 42: 1052 \end{cfa} 1053 \end{tabular} 1054 \lstMakeShortInline@% 1055 \end{cquote} 1056 and a combination: 1057 \begin{cfa} 1058 case -12~-4, -1~5, 14~21, 34~42: 1059 \end{cfa} 1060 1061 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1062 \begin{cfa} 1063 switch ( i ) { 1064 case 0: 1065 for ( int i = 0; i < 10; i += 1 ) { 1066 ... 1067 `case 1:` // no initialization of loop index 1068 ... 1069 } 1070 } 1071 \end{cfa} 1072 \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. 1073 1074 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1075 \begin{cfa} 1076 switch ( x ) { 1077 `int y = 1;` $\C{// unreachable initialization}$ 1078 `x = 7;` $\C{// unreachable code without label/branch}$ 1079 case 0: 1080 ... 1081 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1082 z = 2; 1083 case 1: 1084 `x = z;` $\C{// without fall through, z is undefined}$ 1085 } 1086 \end{cfa} 1087 \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. 1088 \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. 1089 1090 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}; 1091 @case@ clauses are made disjoint by the @break@ statement. 1092 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. 1093 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}). 1094 1095 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1096 1097 \begin{figure} 1098 \centering 1099 \lstDeleteShortInline@% 1100 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1101 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1102 \begin{cfa} 1103 `choose` ( day ) { 1104 case Mon~Thu: // program 1105 1106 case Fri: // program 1107 wallet += pay; 1108 `fallthrough;` 1109 case Sat: // party 1110 wallet -= party; 1111 1112 case Sun: // rest 1113 1114 default: // error 1115 } 1116 \end{cfa} 1117 & 1118 \begin{cfa} 1119 switch ( day ) { 1120 case Mon: case Tue: case Wed: case Thu: // program 1121 `break;` 1122 case Fri: // program 1123 wallet += pay; 1124 1125 case Sat: // party 1126 wallet -= party; 1127 `break;` 1128 case Sun: // rest 1129 `break;` 1130 default: // error 1131 } 1132 \end{cfa} 1133 \end{tabular} 1134 \lstMakeShortInline@% 1135 \caption{\lstinline|choose| versus \lstinline|switch| Statements} 1136 \label{f:ChooseSwitchStatements} 1137 \end{figure} 1138 1139 \begin{comment} 1140 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. 1141 \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. 1142 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. 1143 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: 1144 1145 \begin{cfa} 1146 choose( i ) { 1147 case 2: 1148 printf("even "); 1149 fallthrough; 1150 case 3: case 5: case 7: 1151 printf("small prime\n"); 1152 case 4,6,8,9: 1153 printf("small composite\n"); 1154 case 13~19: 1155 printf("teen\n"); 1156 default: 1157 printf("something else\n"); 1158 } 1159 \end{cfa} 1160 \end{comment} 991 1161 992 1162 … … 1048 1218 } else { 1049 1219 ... goto `LIF`; ... 1050 } `L 3:` ;1220 } `LIF:` ; 1051 1221 } `LS:` ; 1052 1222 } `LC:` ; … … 1082 1252 \end{figure} 1083 1253 1084 Both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:1254 With respect to safety, both labelled @continue@ and @break@ are a @goto@ restricted in the following ways: 1085 1255 \begin{itemize} 1086 1256 \item … … 1095 1265 With @goto@, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader. 1096 1266 Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs. 1097 The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed. 1098 1099 1100 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}} 1101 1102 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. 1103 1104 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.}. 1105 \CFA provides a shorthand for a non-contiguous list: 1267 Otherwise, the implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed. 1268 1269 1270 \subsection{Exception Handling} 1271 1272 The following framework for \CFA exception handling is in place, excluding some run-time type-information and dynamic casts. 1273 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}. 1274 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. 1275 \CFA restricts exception types to those defined by aggregate type @exception@. 1276 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@). 1277 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation. 1278 If there is no current exception, the reresume/rethrow results in a runtime error. 1279 1280 \begin{figure} 1106 1281 \begin{cquote} 1107 1282 \lstDeleteShortInline@% 1108 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1109 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1110 \begin{cfa} 1111 case 2, 10, 34, 42: 1112 \end{cfa} 1113 & 1114 \begin{cfa} 1115 case 2: case 10: case 34: case 42: 1283 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1284 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\ 1285 \begin{cfa} 1286 `exception R { int fix; };` 1287 void f() { 1288 R r; 1289 ... `resume( r );` ... 1290 ... r.fix // control does return here after handler 1291 } 1292 `try` { 1293 ... f(); ... 1294 } `catchResume( R r )` { 1295 ... r.fix = ...; // return correction to raise 1296 } // dynamic return to _Resume 1297 \end{cfa} 1298 & 1299 \begin{cfa} 1300 `exception T {};` 1301 void f() { 1302 1303 ... `throw( T{} );` ... 1304 // control does NOT return here after handler 1305 } 1306 `try` { 1307 ... f(); ... 1308 } `catch( T t )` { 1309 ... // recover and continue 1310 } // static return to next statement 1116 1311 \end{cfa} 1117 1312 \end{tabular} 1118 1313 \lstMakeShortInline@% 1119 1314 \end{cquote} 1120 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1315 \caption{\CFA Exception Handling} 1316 \label{f:CFAExceptionHandling} 1317 \end{figure} 1318 1319 The set of exception types in a list of catch clause may include both a resumption and termination handler: 1320 \begin{cfa} 1321 try { 1322 ... resume( `R{}` ); ... 1323 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$ 1324 catch( `R` r ) { ... } $\C{\color{red}// H2}$ 1325 1326 \end{cfa} 1327 The resumption propagation raises @R@ and the stack is not unwound; 1328 the exception is caught by the @catchResume@ clause and handler H1 is invoked. 1329 The termination propagation in handler H1 raises @R@ and the stack is unwound; 1330 the exception is caught by the @catch@ clause and handler H2 is invoked. 1331 The termination handler is available because the resumption propagation did not unwind the stack. 1332 1333 An additional feature is conditional matching in a catch clause: 1334 \begin{cfa} 1335 try { 1336 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$ 1337 ... write( `logfile`, ... ); ... 1338 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$ 1339 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$ 1340 catch ( IOError err ) { ... } $\C{// handler error from other files}$ 1341 \end{cfa} 1342 where the throw inserts the failing file-handle in the I/O exception. 1343 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.. 1344 1345 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}: 1346 \begin{cfa} 1347 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ ) 1348 resume( $\emph{alternate-stack}$ ) 1349 \end{cfa} 1350 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another \CFA coroutine or task~\cite{Delisle18}.\footnote{\CFA coroutine and concurrency features are discussed in a separately submitted paper.} 1351 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. 1352 1353 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation. 1354 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks: 1121 1355 \begin{cquote} 1122 1356 \lstDeleteShortInline@% 1123 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1124 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1125 \begin{cfa} 1126 case 2~42: 1127 \end{cfa} 1128 & 1129 \begin{cfa} 1130 case 2: case 3: ... case 41: case 42: 1357 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1358 \begin{cfa} 1359 enable $\emph{exception-type-list}$ { 1360 // allow non-local resumption 1361 } 1362 \end{cfa} 1363 & 1364 \begin{cfa} 1365 disable $\emph{exception-type-list}$ { 1366 // disallow non-local resumption 1367 } 1131 1368 \end{cfa} 1132 1369 \end{tabular} 1133 1370 \lstMakeShortInline@% 1134 1371 \end{cquote} 1135 and a combination: 1136 \begin{cfa} 1137 case -12~-4, -1~5, 14~21, 34~42: 1138 \end{cfa} 1139 1140 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1141 \begin{cfa} 1142 switch ( i ) { 1143 case 0: 1144 for ( int i = 0; i < 10; i += 1 ) { 1145 ... 1146 `case 1:` // no initialization of loop index 1147 ... 1372 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively. 1373 Specifying no exception type is shorthand for specifying all exception types. 1374 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. 1375 Coroutines and tasks start with non-local exceptions disabled, allowing handlers to be put in place, before non-local exceptions are explicitly enabled. 1376 \begin{cfa} 1377 void main( mytask & c ) { 1378 try { 1379 enable { $\C{// now allow non-local exception delivery}$ 1380 // task body 1381 } 1382 // appropriate catchResume/catch 1148 1383 } 1149 1384 } 1150 1385 \end{cfa} 1151 \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. 1152 1153 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1154 \begin{cfa} 1155 switch ( x ) { 1156 `int y = 1;` $\C{// unreachable initialization}$ 1157 `x = 7;` $\C{// unreachable code without label/branch}$ 1158 case 0: 1159 ... 1160 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1161 z = 2; 1162 case 1: 1163 `x = z;` $\C{// without fall through, z is undefined}$ 1164 } 1165 \end{cfa} 1166 \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. 1167 \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. 1168 1169 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}; 1170 @case@ clauses are made disjoint by the @break@ statement. 1171 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. 1172 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}). 1173 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1174 1175 \begin{figure} 1176 \centering 1177 \lstDeleteShortInline@% 1178 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1179 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1180 \begin{cfa} 1181 `choose` ( day ) { 1182 case Mon~Thu: // program 1183 1184 case Fri: // program 1185 wallet += pay; 1186 `fallthrough;` 1187 case Sat: // party 1188 wallet -= party; 1189 1190 case Sun: // rest 1191 1192 default: // error 1193 } 1194 \end{cfa} 1195 & 1196 \begin{cfa} 1197 switch ( day ) { 1198 case Mon: case Tue: case Wed: case Thu: // program 1199 `break;` 1200 case Fri: // program 1201 wallet += pay; 1202 1203 case Sat: // party 1204 wallet -= party; 1205 `break;` 1206 case Sun: // rest 1207 `break;` 1208 default: // error 1209 } 1210 \end{cfa} 1211 \end{tabular} 1212 \lstMakeShortInline@% 1213 \caption{\lstinline|choose| versus \lstinline|switch| Statements} 1214 \label{f:ChooseSwitchStatements} 1215 \end{figure} 1216 1217 \begin{comment} 1218 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. 1219 \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. 1220 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. 1221 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: 1222 1223 \begin{cfa} 1224 choose( i ) { 1225 case 2: 1226 printf("even "); 1227 fallthrough; 1228 case 3: case 5: case 7: 1229 printf("small prime\n"); 1230 case 4,6,8,9: 1231 printf("small composite\n"); 1232 case 13~19: 1233 printf("teen\n"); 1234 default: 1235 printf("something else\n"); 1236 } 1237 \end{cfa} 1238 \end{comment} 1386 1387 Finally, \CFA provides a Java like @finally@ clause after the catch clauses: 1388 \begin{cfa} 1389 try { 1390 ... f(); ... 1391 // catchResume or catch clauses 1392 } `finally` { 1393 // house keeping 1394 } 1395 \end{cfa} 1396 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised. 1397 If an exception is raised and caught, the handler is run before the finally clause. 1398 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated. 1399 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses. 1239 1400 1240 1401 … … 1251 1412 S s, as[10]; 1252 1413 \end{cfa} 1253 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:1414 However, functions manipulating aggregates must repeat the aggregate name to access its containing fields: 1254 1415 \begin{cfa} 1255 1416 void f( S s ) { … … 1269 1430 } 1270 1431 \end{C++} 1271 Object-oriented nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.1432 Object-oriented nesting of member functions in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping. 1272 1433 However, for other aggregate parameters, qualification is necessary: 1273 1434 \begin{cfa} … … 1299 1460 'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$ 1300 1461 \end{cfa} 1301 and may appear as the body of a routine or nested within a routinebody.1462 and may appear as the body of a function or nested within a function body. 1302 1463 Each expression in the expression-list provides a type and object. 1303 1464 The type must be an aggregate type. … … 1326 1487 Qualification or a cast is used to disambiguate. 1327 1488 1328 There is an interesting problem between parameters and the routine@with@, \eg:1489 There is an interesting problem between parameters and the function-body @with@, \eg: 1329 1490 \begin{cfa} 1330 1491 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ … … 1332 1493 } 1333 1494 \end{cfa} 1334 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@.1495 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-body @with@. 1335 1496 To solve this problem, parameters are treated like an initialized aggregate: 1336 1497 \begin{cfa} … … 1340 1501 } params; 1341 1502 \end{cfa} 1342 and implicitly opened \emph{after} a routineopen, to give them higher priority:1343 \begin{cfa} 1344 void ?{}( S & s, int i) with ( s ) `with( $\emph{\color{red}params}$ )` {1345 s.i = i; j = 3; m = 5.5;1503 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1504 \begin{cfa} 1505 void ?{}( S & s, int `i` ) with ( s ) `with( $\emph{\color{red}params}$ )` { 1506 s.i = `i`; j = 3; m = 5.5; 1346 1507 } 1347 1508 \end{cfa} … … 1368 1529 1369 1530 1370 \subsection{Exception Handling}1371 1372 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.1373 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).1374 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.1375 \CFA restricts exception types to those defined by aggregate type @exception@.1376 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@).1377 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.1378 If there is no current exception, the reresume/rethrow results in a runtime error.1379 1380 \begin{figure}1381 \begin{cquote}1382 \lstDeleteShortInline@%1383 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}1384 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\1385 \begin{cfa}1386 `exception R { int fix; };`1387 void f() {1388 R r;1389 ... `resume( r );` ...1390 ... r.fix // control does return here after handler1391 }1392 `try` {1393 ... f(); ...1394 } `catchResume( R r )` {1395 ... r.fix = ...; // return correction to raise1396 } // dynamic return to _Resume1397 \end{cfa}1398 &1399 \begin{cfa}1400 `exception T {};`1401 void f() {1402 1403 ... `throw( T{} );` ...1404 // control does NOT return here after handler1405 }1406 `try` {1407 ... f(); ...1408 } `catch( T t )` {1409 ... // recover and continue1410 } // static return to next statement1411 \end{cfa}1412 \end{tabular}1413 \lstMakeShortInline@%1414 \end{cquote}1415 \caption{\CFA Exception Handling}1416 \label{f:CFAExceptionHandling}1417 \end{figure}1418 1419 The set of exception types in a list of catch clause may include both a resumption and termination handler:1420 \begin{cfa}1421 try {1422 ... resume( `R{}` ); ...1423 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$1424 catch( `R` r ) { ... } $\C{\color{red}// H2}$1425 1426 \end{cfa}1427 The resumption propagation raises @R@ and the stack is not unwound;1428 the exception is caught by the @catchResume@ clause and handler H1 is invoked.1429 The termination propagation in handler H1 raises @R@ and the stack is unwound;1430 the exception is caught by the @catch@ clause and handler H2 is invoked.1431 The termination handler is available because the resumption propagation did not unwind the stack.1432 1433 An additional feature is conditional matching in a catch clause:1434 \begin{cfa}1435 try {1436 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$1437 ... write( `logfile`, ... ); ...1438 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$1439 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$1440 catch ( IOError err ) { ... } $\C{// handler error from other files}$1441 \end{cfa}1442 where the throw inserts the failing file-handle in the I/O exception.1443 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..1444 1445 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:1446 \begin{cfa}1447 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )1448 resume( $\emph{alternate-stack}$ )1449 \end{cfa}1450 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.1451 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.1452 1453 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.1454 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:1455 \begin{cquote}1456 \lstDeleteShortInline@%1457 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}1458 \begin{cfa}1459 enable $\emph{exception-type-list}$ {1460 // allow non-local resumption1461 }1462 \end{cfa}1463 &1464 \begin{cfa}1465 disable $\emph{exception-type-list}$ {1466 // disallow non-local resumption1467 }1468 \end{cfa}1469 \end{tabular}1470 \lstMakeShortInline@%1471 \end{cquote}1472 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.1473 Specifying no exception type is shorthand for specifying all exception types.1474 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.1475 1476 Finally, \CFA provides a Java like @finally@ clause after the catch clauses:1477 \begin{cfa}1478 try {1479 ... f(); ...1480 // catchResume or catch clauses1481 } `finally` {1482 // house keeping1483 }1484 \end{cfa}1485 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.1486 If an exception is raised and caught, the handler is run before the finally clause.1487 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.1488 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.1489 1490 1491 1531 \section{Declarations} 1492 1532 … … 1516 1556 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers? 1517 1557 If there is any doubt, it implies productivity and safety issues even for basic programs. 1518 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.1519 For example, a routinereturning a pointer to an array of integers is defined and used in the following way:1558 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. 1559 For example, a function returning a pointer to an array of integers is defined and used in the following way: 1520 1560 \begin{cfa} 1521 1561 int `(*`f`())[`5`]` {...}; $\C{// definition}$ 1522 1562 ... `(*`f`())[`3`]` += 1; $\C{// usage}$ 1523 1563 \end{cfa} 1524 Essentially, the return type is wrapped around the routinename in successive layers (like an onion).1564 Essentially, the return type is wrapped around the function name in successive layers (like an onion). 1525 1565 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice. 1526 1566 1527 \CFA provides its own type, variable and routine declarations, using a different syntax.1567 \CFA provides its own type, variable and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}. 1528 1568 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right. 1529 1569 The qualifiers have the same meaning but are ordered left to right to specify a variable's type. … … 1553 1593 \end{cquote} 1554 1594 The only exception is bit field specification, which always appear to the right of the base type. 1555 % 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.1595 % 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. 1556 1596 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1557 1597 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows: … … 1639 1679 \lstMakeShortInline@% 1640 1680 \end{cquote} 1641 Specifiers must appear at the start of a \CFA routinedeclaration\footnote{\label{StorageClassSpecifier}1681 Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier} 1642 1682 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}}. 1643 1683 1644 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo- routine@sizeof@:1684 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@: 1645 1685 \begin{cquote} 1646 1686 \lstDeleteShortInline@% … … 1660 1700 \end{cquote} 1661 1701 1662 The syntax of the new routine prototype declaration follows directly from the new routinedefinition syntax;1702 The syntax of the new function-prototype declaration follows directly from the new function-definition syntax; 1663 1703 as well, parameter names are optional, \eg: 1664 1704 \begin{cfa} … … 1669 1709 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$ 1670 1710 \end{cfa} 1671 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routinedefinition header (or vice versa).1672 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:1711 This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa). 1712 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: 1673 1713 \begin{cquote} 1674 1714 \lstDeleteShortInline@% … … 1685 1725 \lstMakeShortInline@% 1686 1726 \end{cquote} 1687 where \CFA allows the last routinein the list to define its body.1688 1689 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:1690 \begin{cfa} 1691 * [ int x ] () fp; $\C{// pointer to routinereturning int with no parameters}$1692 * [ * int ] ( int y ) gp; $\C{// pointer to routinereturning pointer to int with int parameter}$1693 * [ ] ( int, char ) hp; $\C{// pointer to routinereturning no result with int and char parameters}$1694 * [ * int, int ] ( int ) jp; $\C{// pointer to routinereturning pointer to int and int, with int parameter}$1695 \end{cfa} 1696 Note, a routinename cannot be specified:1697 \begin{cfa} 1698 * [ int x ] f () fp; $\C{// routinename "f" is disallowed}$1727 where \CFA allows the last function in the list to define its body. 1728 1729 The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg: 1730 \begin{cfa} 1731 * [ int x ] () fp; $\C{// pointer to function returning int with no parameters}$ 1732 * [ * int ] ( int y ) gp; $\C{// pointer to function returning pointer to int with int parameter}$ 1733 * [ ] ( int, char ) hp; $\C{// pointer to function returning no result with int and char parameters}$ 1734 * [ * int, int ] ( int ) jp; $\C{// pointer to function returning pointer to int and int, with int parameter}$ 1735 \end{cfa} 1736 Note, a function name cannot be specified: 1737 \begin{cfa} 1738 * [ int x ] f () fp; $\C{// function name "f" is disallowed}$ 1699 1739 \end{cfa} 1700 1740 … … 1916 1956 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}. 1917 1957 \begin{cfa} 1918 struct VLA { 1919 int len, * data; 1920 }; 1921 void ?{}( VLA & vla ) with ( vla ) { $\C{// default constructor}$ 1922 len = 10; data = alloc( len ); $\C{// shallow copy}$ 1923 } 1924 void ^?{}( VLA & vla ) with ( vla ) { $\C{// destructor}$ 1925 free( data ); 1926 } 1958 struct VLA { int len, * data; }; 1959 void ?{}( VLA & vla ) with ( vla ) { len = 10; data = alloc( len ); } $\C{// default constructor}$ 1960 void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$ 1927 1961 { 1928 1962 VLA x; $\C{// implicit: ?\{\}( x );}$ 1929 1963 } $\C{// implicit: ?\^{}\{\}( x );}$ 1930 1964 \end{cfa} 1931 (Note, the example is purposely kept simple by using shallow-copy semantics.)1932 1965 @VLA@ is a \newterm{managed type}\footnote{ 1933 1966 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. … … 1937 1970 \CFA also provides syntax for \newterm{initialization} and \newterm{copy}: 1938 1971 \begin{cfa} 1939 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { 1972 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { $\C{// initialization}$ 1940 1973 len = size; data = alloc( len, fill ); 1941 1974 } 1942 void ?{}( VLA & vla, VLA other ) { $\C{// copy }$1975 void ?{}( VLA & vla, VLA other ) { $\C{// copy, shallow}$ 1943 1976 vla.len = other.len; vla.data = other.data; 1944 1977 } 1945 1978 \end{cfa} 1979 (Note, the example is purposely simplified using shallow-copy semantics.) 1946 1980 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). 1947 1981 \begin{cfa} … … 1957 1991 \begin{cfa} 1958 1992 { 1959 VLA x, y = { 20, 0x01 }, z = y;1960 // implicit: ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); z points to y1993 VLA x, y = { 20, 0x01 }, z = y; $\C{// z points to y}$ 1994 // ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); 1961 1995 ^x{}; $\C{// deallocate x}$ 1962 1996 x{}; $\C{// reallocate x}$ … … 1965 1999 y{ x }; $\C{// reallocate y, points to x}$ 1966 2000 x{}; $\C{// reallocate x, not pointing to y}$ 1967 // implicit:^?{}(z); ^?{}(y); ^?{}(x);2001 // ^?{}(z); ^?{}(y); ^?{}(x); 1968 2002 } 1969 2003 \end{cfa} … … 1996 2030 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. 1997 2031 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. 1998 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@. 2032 2033 A simple 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@, where the underscore is also the standard separator in C identifiers. 2034 \CC uses a single quote as a separator but it is restricted among digits, precluding its use in the literal prefix or suffix, \eg @0x1.ffff@@`'@@ffffp128l@, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote. 2035 2036 2037 \subsection{Integral Suffixes} 2038 2039 Additional integral suffixes are added to cover all the integral types and lengths. 2040 \begin{cquote} 2041 \lstDeleteShortInline@% 2042 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2043 \begin{cfa} 2044 20_`hh` // signed char 2045 21_`hhu` // unsigned char 2046 22_`h` // signed short int 2047 23_`uh` // unsigned short int 2048 24_`z` // size_t 2049 \end{cfa} 2050 & 2051 \begin{cfa} 2052 20_`L8` // int8_t 2053 21_`ul8` // uint8_t 2054 22_`l16` // int16_t 2055 23_`ul16` // uint16_t 2056 24_`l32` // int32_t 2057 \end{cfa} 2058 & 2059 \begin{cfa} 2060 25_`ul32` // uint32_t 2061 26_`l64` // int64_t 2062 27_`l64u` // uint64_t 2063 26_`L128` // int128 2064 27_`L128u` // unsigned int128 2065 \end{cfa} 2066 \end{tabular} 2067 \lstMakeShortInline@% 2068 \end{cquote} 1999 2069 2000 2070 … … 2013 2083 2014 2084 2015 \subsection{Integral Suffixes} 2016 2017 Additional integral suffixes are added to cover all the integral types and lengths. 2018 \begin{cquote} 2085 \subsection{User Literals} 2086 2087 For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours). 2088 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. 2089 The backquote is a small character, making the unit (function name) predominate. 2090 For examples, the multi-precision integers in Section~\ref{s:MultiPrecisionIntegers} make use of user literals: 2091 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2092 \begin{cfa} 2093 y = 9223372036854775807L|`mp| * 18446744073709551615UL|`mp|; 2094 y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|; 2095 \end{cfa} 2096 Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions. 2097 }% 2098 2099 The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax. 2100 However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals. 2101 After which, user literals must match (no conversions); 2102 hence, it is necessary to overload the unit with all appropriate types. 2103 2104 \begin{figure} 2105 \centering 2106 \lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2019 2107 \lstDeleteShortInline@% 2020 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2021 \begin{cfa} 2022 20_hh // signed char 2023 21_hhu // unsigned char 2024 22_h // signed short int 2025 23_uh // unsigned short int 2026 24z // size_t 2027 \end{cfa} 2028 & 2029 \begin{cfa} 2030 20_L8 // int8_t 2031 21_ul8 // uint8_t 2032 22_l16 // int16_t 2033 23_ul16 // uint16_t 2034 24_l32 // int32_t 2035 \end{cfa} 2036 & 2037 \begin{cfa} 2038 25_ul32 // uint32_t 2039 26_l64 // int64_t 2040 27_l64u // uint64_t 2041 26_L128 // int128 2042 27_L128u // unsigned int128 2108 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2109 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 2110 \begin{cfa} 2111 struct W { 2112 double stones; 2113 }; 2114 void ?{}( W & w ) { w.stones = 0; } 2115 void ?{}( W & w, double w ) { w.stones = w; } 2116 W ?+?( W l, W r ) { 2117 return (W){ l.stones + r.stones }; 2118 } 2119 W |?`st|( double w ) { return (W){ w }; } 2120 W |?`lb|( double w ) { return (W){ w / 14.0 }; } 2121 W |?`kg|( double w ) { return (W) { w * 0.16 }; } 2122 2123 2124 2125 int main() { 2126 W w, heavy = { 20 }; 2127 w = 155|`lb|; 2128 w = 0b_1111|`st|; 2129 w = 0_233|`lb|; 2130 w = 0x_9b_u|`kg|; 2131 w = 5.5|`st| + 8|`kg| + 25.01|`lb| + heavy; 2132 } 2133 \end{cfa} 2134 & 2135 \begin{cfa} 2136 struct W { 2137 double stones; 2138 W() { stones = 0.0; } 2139 W( double w ) { stones = w; } 2140 }; 2141 W operator+( W l, W r ) { 2142 return W( l.stones + r.stones ); 2143 } 2144 W |operator"" _st|( unsigned long long int w ) { return W( w ); } 2145 W |operator"" _lb|( unsigned long long int w ) { return W( w / 14.0 ); } 2146 W |operator"" _kg|( unsigned long long int w ) { return W( w * 0.16 ); } 2147 W |operator"" _st|( long double w ) { return W( w ); } 2148 W |operator"" _lb|( long double w ) { return W( w / 14.0 ); } 2149 W |operator"" _kg|( long double w ) { return W( w * 0.16 ); } 2150 int main() { 2151 W w, heavy = { 20 }; 2152 w = 155|_lb|; 2153 w = 0b1111|_lb|; // error, binary unsupported 2154 w = 0${\color{red}\LstBasicStyle{'}}$233|_lb|; // quote separator 2155 w = 0x9b|_kg|; 2156 w = 5.5d|_st| + 8|_kg| + 25.01|_lb| + heavy; 2157 } 2043 2158 \end{cfa} 2044 2159 \end{tabular} 2045 2160 \lstMakeShortInline@% 2046 \end{cquote} 2047 2048 2049 \subsection{Units} 2050 2051 Alternative call syntax (literal argument before routine name) to convert basic literals into user literals. 2052 2053 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2054 \begin{cfa} 2055 struct Weight { double stones; }; 2056 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$ 2057 void ?{}( Weight & w, double w ) { w.stones = w; } 2058 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } 2059 2060 Weight |?`st|( double w ) { return (Weight){ w }; } $\C{// backquote for units}$ 2061 Weight |?`lb|( double w ) { return (Weight){ w / 14.0 }; } 2062 Weight |?`kg|( double w ) { return (Weight) { w * 0.1575}; } 2063 2064 int main() { 2065 Weight w, heavy = { 20 }; $\C{// 20 stone}$ 2066 w = 155|`lb|; 2067 w = 0x_9b_u|`lb|; $\C{// hexadecimal unsigned weight (155)}$ 2068 w = 0_233|`lb|; $\C{// octal weight (155)}$ 2069 w = 5|`st| + 8|`kg| + 25|`lb| + heavy; 2070 } 2071 \end{cfa} 2072 }% 2161 \caption{User Literal} 2162 \label{f:UserLiteral} 2163 \end{figure} 2073 2164 2074 2165 … … 2080 2171 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime. 2081 2172 The following sections give a glimpse of the interface reduction to many C libraries. 2082 In many cases, @signed@/@unsigned@ @char@, @short@, and @_Complex@ routines are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results.2173 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. 2083 2174 2084 2175 … … 2108 2199 \begin{cquote} 2109 2200 \lstDeleteShortInline@% 2110 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2111 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2201 \lstset{basicstyle=\linespread{0.9}\sf\small} 2202 \begin{tabular}{@{}l@{\hspace{0.5\parindentlnth}}l@{}} 2203 \multicolumn{1}{c@{\hspace{0.5\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2112 2204 \begin{cfa} 2113 2205 MIN 2114 2115 2206 MAX 2116 2117 2207 PI 2118 2208 E … … 2120 2210 & 2121 2211 \begin{cfa} 2122 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, 2123 FLT_MIN, DBL_MIN, LDBL_MIN 2124 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, 2125 FLT_MAX, DBL_MAX, LDBL_MAX 2212 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN 2213 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX 2126 2214 M_PI, M_PIl 2127 2215 M_E, M_El … … 2134 2222 \subsection{Math} 2135 2223 2136 C library @math.h@ provides many mathematical routines.2137 \CFA routine overloading is used to condense these mathematical routines, \eg:2224 C library @math.h@ provides many mathematical functions. 2225 \CFA function overloading is used to condense these mathematical functions, \eg: 2138 2226 \begin{cquote} 2139 2227 \lstDeleteShortInline@% … … 2154 2242 \lstMakeShortInline@% 2155 2243 \end{cquote} 2156 The result is a significant reduction in names to access math routines, \eg:2244 The result is a significant reduction in names to access math functions, \eg: 2157 2245 \begin{cquote} 2158 2246 \lstDeleteShortInline@% … … 2173 2261 \lstMakeShortInline@% 2174 2262 \end{cquote} 2175 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).2263 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). 2176 2264 For example, it is impossible to overload @atan@ for both one and two arguments; 2177 2265 instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}). 2178 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.2266 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. 2179 2267 2180 2268 2181 2269 \subsection{Standard} 2182 2270 2183 C library @stdlib.h@ provides many general routines.2184 \CFA routine overloading is used to condense these utility routines, \eg:2271 C library @stdlib.h@ provides many general functions. 2272 \CFA function overloading is used to condense these utility functions, \eg: 2185 2273 \begin{cquote} 2186 2274 \lstDeleteShortInline@% … … 2201 2289 \lstMakeShortInline@% 2202 2290 \end{cquote} 2203 The result is a significant reduction in names to access utility routines, \eg:2291 The result is a significant reduction in names to access utility functions, \eg: 2204 2292 \begin{cquote} 2205 2293 \lstDeleteShortInline@% … … 2220 2308 \lstMakeShortInline@% 2221 2309 \end{cquote} 2222 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.2310 In additon, there are polymorphic functions, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@. 2223 2311 2224 2312 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety. … … 2226 2314 \begin{description}[topsep=3pt,itemsep=2pt,parsep=0pt] 2227 2315 \item[fill] 2228 a fter allocation the storage is filledwith a specified character.2316 an allocation with a specified character. 2229 2317 \item[resize] 2230 an existing allocation is decreased or increased insize.2318 an existing allocation to decreased or increased its size. 2231 2319 In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied. 2232 2320 For an increase in storage size, new storage after the copied data may be filled. 2233 2321 \item[alignment] 2234 an allocation startson a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.2322 an allocation on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes. 2235 2323 \item[array] 2236 the allocation size is scaled to the specified number of arrayelements.2324 allocation of the specified number of elements. 2237 2325 An array may be filled, resized, or aligned. 2238 2326 \end{description} 2239 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. 2240 2241 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2242 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety: 2243 \begin{cquote} 2244 \begin{cfa}[aboveskip=0pt] 2245 size_t dim = 10; $\C{// array dimension}$ 2246 char fill = '\xff'; $\C{// initialization fill value}$ 2247 int * ip; 2248 \end{cfa} 2249 \lstDeleteShortInline@% 2250 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2251 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2252 \begin{cfa} 2253 ip = alloc(); 2254 ip = alloc( fill ); 2255 ip = alloc( dim ); 2256 ip = alloc( dim, fill ); 2257 ip = alloc( ip, 2 * dim ); 2258 ip = alloc( ip, 4 * dim, fill ); 2259 2260 ip = align_alloc( 16 ); 2261 ip = align_alloc( 16, fill ); 2262 ip = align_alloc( 16, dim ); 2263 ip = align_alloc( 16, dim, fill ); 2264 \end{cfa} 2265 & 2266 \begin{cfa} 2267 ip = (int *)malloc( sizeof( int ) ); 2268 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2269 ip = (int *)malloc( dim * sizeof( int ) ); 2270 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2271 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2272 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2273 2274 ip = memalign( 16, sizeof( int ) ); 2275 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2276 ip = memalign( 16, dim * sizeof( int ) ); 2277 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2278 \end{cfa} 2279 \end{tabular} 2280 \lstMakeShortInline@% 2281 \end{cquote} 2282 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2283 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg: 2284 \begin{cfa} 2285 struct S { int i, j; }; 2286 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2287 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2288 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2289 \end{cfa} 2290 Note, \CC can only initialization array elements via the default constructor. 2291 2292 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. 2293 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2327 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. 2328 \CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2329 Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation performing the same operations with the same type safety. 2294 2330 2295 2331 \begin{table} … … 2317 2353 \end{table} 2318 2354 2355 \begin{figure} 2356 \centering 2357 \begin{cquote} 2358 \begin{cfa}[aboveskip=0pt] 2359 size_t dim = 10; $\C{// array dimension}$ 2360 char fill = '\xff'; $\C{// initialization fill value}$ 2361 int * ip; 2362 \end{cfa} 2363 \lstDeleteShortInline@% 2364 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2365 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2366 \begin{cfa} 2367 ip = alloc(); 2368 ip = alloc( fill ); 2369 ip = alloc( dim ); 2370 ip = alloc( dim, fill ); 2371 ip = alloc( ip, 2 * dim ); 2372 ip = alloc( ip, 4 * dim, fill ); 2373 2374 ip = align_alloc( 16 ); 2375 ip = align_alloc( 16, fill ); 2376 ip = align_alloc( 16, dim ); 2377 ip = align_alloc( 16, dim, fill ); 2378 \end{cfa} 2379 & 2380 \begin{cfa} 2381 ip = (int *)malloc( sizeof( int ) ); 2382 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2383 ip = (int *)malloc( dim * sizeof( int ) ); 2384 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2385 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2386 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2387 2388 ip = memalign( 16, sizeof( int ) ); 2389 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2390 ip = memalign( 16, dim * sizeof( int ) ); 2391 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2392 \end{cfa} 2393 \end{tabular} 2394 \lstMakeShortInline@% 2395 \end{cquote} 2396 \caption{\CFA versus C Storage-Allocation} 2397 \label{f:StorageAllocation} 2398 \end{figure} 2399 2400 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2401 Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg: 2402 \begin{cfa} 2403 struct S { int i, j; }; 2404 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2405 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2406 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2407 \end{cfa} 2408 Note, \CC can only initialization array elements via the default constructor. 2409 2410 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. 2411 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2412 2319 2413 2320 2414 \subsection{I/O} … … 2376 2470 \end{cfa} 2377 2471 \\ 2378 \textbf{output:}2379 2472 & 2380 2473 \begin{cfa}[showspaces=true,aboveskip=0pt] … … 2404 2497 }% 2405 2498 \end{itemize} 2406 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.2499 There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output. 2407 2500 2408 2501 … … 2411 2504 2412 2505 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP. 2413 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.2506 The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers. 2414 2507 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@. 2415 2508 The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces. … … 2456 2549 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. 2457 2550 A more illustrative benchmark measures the costs of idiomatic usage of each language's features. 2458 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}.2551 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}. 2459 2552 The benchmark test is similar for C and \CC. 2460 2553 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. … … 2463 2556 \begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt] 2464 2557 int main( int argc, char * argv[] ) { 2465 ofstream out = { "cfa-out.txt" };2466 2558 int max = 0, val = 42; 2467 stack( int ) si, t ;2559 stack( int ) si, ti; 2468 2560 2469 2561 REPEAT_TIMED( "push_int", N, push( si, val ); ) 2470 TIMED( "copy_int", t = si; )2562 TIMED( "copy_int", ti = si; ) 2471 2563 TIMED( "clear_int", clear( si ); ) 2472 REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); )2473 REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )2564 REPEAT_TIMED( "pop_int", N, 2565 int x = pop( ti ); if ( x > max ) max = x; ) 2474 2566 2475 2567 pair( _Bool, char ) max = { (_Bool)0, '\0' }, val = { (_Bool)1, 'a' }; 2476 stack( pair( _Bool, char ) ) s , t;2477 2478 REPEAT_TIMED( "push_pair", N, push( s , val ); )2479 TIMED( "copy_pair", t = s; )2480 TIMED( "clear_pair", clear( s ); )2481 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); )2482 REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )2568 stack( pair( _Bool, char ) ) sp, tp; 2569 2570 REPEAT_TIMED( "push_pair", N, push( sp, val ); ) 2571 TIMED( "copy_pair", tp = sp; ) 2572 TIMED( "clear_pair", clear( sp ); ) 2573 REPEAT_TIMED( "pop_pair", N, 2574 pair(_Bool, char) x = pop( tp ); if ( x > max ) max = x; ) 2483 2575 } 2484 2576 \end{cfa} … … 2551 2643 \CC is the most similar language to \CFA; 2552 2644 both are extensions to C with source and runtime backwards compatibility. 2553 The fundamental difference is in their engineering approach toC compatibility and programmer expectation.2554 While \CC provides good backwardscompatibility with C, it has a steep learning curve for many of its extensions.2645 The fundamental difference is the engineering approach to maintain C compatibility and programmer expectation. 2646 While \CC provides good compatibility with C, it has a steep learning curve for many of its extensions. 2555 2647 For example, polymorphism is provided via three disjoint mechanisms: overloading, inheritance, and templates. 2556 2648 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. 2557 2649 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. 2558 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed properties for a type.2559 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;2650 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties. 2651 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; 2560 2652 furthermore, \CC concepts are restricted to template polymorphism. 2561 2653 … … 2608 2700 2609 2701 2702 \subsection{Control Structures / Declarations / Literals} 2703 2704 Java has default fall through like C/\CC. 2705 Pascal/Ada/Go/Rust do not have default fall through. 2706 \Csharp does not have fall through but still requires a break. 2707 Python uses dictionary mapping. \\ 2708 \CFA choose is like Rust match. 2709 2710 Java has labelled break/continue. \\ 2711 Languages with and without exception handling. 2712 2713 Alternative C declarations. \\ 2714 Different references \\ 2715 Constructors/destructors 2716 2717 0/1 Literals \\ 2718 user defined: D, Objective-C 2719 2610 2720 \section{Conclusion and Future Work} 2611 2721 … … 2613 2723 While other programming languages purport to be a better C, they are in fact new and interesting languages in their own right, but not C extensions. 2614 2724 The purpose of this paper is to introduce \CFA, and showcase language features that illustrate the \CFA type-system and approaches taken to achieve the goal of evolutionary C extension. 2615 The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, and tuples, which all have complex interactions.2725 The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, tuples, advanced control structures, and extended declarations, which all have complex interactions. 2616 2726 The work is a challenging design, engineering, and implementation exercise. 2617 2727 On the surface, the project may appear as a rehash of similar mechanisms in \CC. … … 2620 2730 Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable. 2621 2731 2622 There is ongoing work on a wide range of \CFA feature extensions, including arrays with size, exceptions, concurrent primitives, modules, and user-defined conversions.2732 There is ongoing work on a wide range of \CFA feature extensions, including arrays with size, user-defined conversions, concurrent primitives, and modules. 2623 2733 (While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these additional extensions.) 2624 2734 In addition, there are interesting future directions for the polymorphism design. … … 2633 2743 \section{Acknowledgments} 2634 2744 2635 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. 2636 %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. 2745 The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, and Andrew Beach on the features described in this paper, and thank Magnus Madsen for feedback in the writing. 2746 This work is supported through a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada. 2747 2637 2748 % 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. 2638 2749 … … 2666 2777 stack_node(T) ** crnt = &s.head; 2667 2778 for ( stack_node(T) * next = t.head; next; next = next->next ) { 2668 *crnt = malloc(){ next->value }; 2779 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2780 (*new_node){ next->value }; /***/ 2781 *crnt = new_node; 2669 2782 stack_node(T) * acrnt = *crnt; 2670 2783 crnt = &acrnt->next; … … 2681 2794 forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; } 2682 2795 forall(otype T) void push( stack(T) & s, T value ) { 2683 s.head = malloc(){ value, s.head }; 2796 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2797 (*new_node){ value, s.head }; /***/ 2798 s.head = new_node; 2684 2799 } 2685 2800 forall(otype T) T pop( stack(T) & s ) { 2686 2801 stack_node(T) * n = s.head; 2687 2802 s.head = n->next; 2688 T x = n->value; 2689 ^n{}; 2690 free( n ); 2691 return x; 2803 T v = n->value; 2804 delete( n ); 2805 return v; 2692 2806 } 2693 2807 forall(otype T) void clear( stack(T) & s ) { … … 2845 2959 2846 2960 2847 \begin{comment}2848 \subsubsection{bench.h}2849 (\texttt{bench.hpp} is similar.)2850 2851 \lstinputlisting{evaluation/bench.h}2852 2853 \subsection{C}2854 2855 \subsubsection{c-stack.h} ~2856 2857 \lstinputlisting{evaluation/c-stack.h}2858 2859 \subsubsection{c-stack.c} ~2860 2861 \lstinputlisting{evaluation/c-stack.c}2862 2863 \subsubsection{c-pair.h} ~2864 2865 \lstinputlisting{evaluation/c-pair.h}2866 2867 \subsubsection{c-pair.c} ~2868 2869 \lstinputlisting{evaluation/c-pair.c}2870 2871 \subsubsection{c-print.h} ~2872 2873 \lstinputlisting{evaluation/c-print.h}2874 2875 \subsubsection{c-print.c} ~2876 2877 \lstinputlisting{evaluation/c-print.c}2878 2879 \subsubsection{c-bench.c} ~2880 2881 \lstinputlisting{evaluation/c-bench.c}2882 2883 \subsection{\CFA}2884 2885 \subsubsection{cfa-stack.h} ~2886 2887 \lstinputlisting{evaluation/cfa-stack.h}2888 2889 \subsubsection{cfa-stack.c} ~2890 2891 \lstinputlisting{evaluation/cfa-stack.c}2892 2893 \subsubsection{cfa-print.h} ~2894 2895 \lstinputlisting{evaluation/cfa-print.h}2896 2897 \subsubsection{cfa-print.c} ~2898 2899 \lstinputlisting{evaluation/cfa-print.c}2900 2901 \subsubsection{cfa-bench.c} ~2902 2903 \lstinputlisting{evaluation/cfa-bench.c}2904 2905 \subsection{\CC}2906 2907 \subsubsection{cpp-stack.hpp} ~2908 2909 \lstinputlisting[language=c++]{evaluation/cpp-stack.hpp}2910 2911 \subsubsection{cpp-print.hpp} ~2912 2913 \lstinputlisting[language=c++]{evaluation/cpp-print.hpp}2914 2915 \subsubsection{cpp-bench.cpp} ~2916 2917 \lstinputlisting[language=c++]{evaluation/cpp-bench.cpp}2918 2919 \subsection{\CCV}2920 2921 \subsubsection{object.hpp} ~2922 2923 \lstinputlisting[language=c++]{evaluation/object.hpp}2924 2925 \subsubsection{cpp-vstack.hpp} ~2926 2927 \lstinputlisting[language=c++]{evaluation/cpp-vstack.hpp}2928 2929 \subsubsection{cpp-vstack.cpp} ~2930 2931 \lstinputlisting[language=c++]{evaluation/cpp-vstack.cpp}2932 2933 \subsubsection{cpp-vprint.hpp} ~2934 2935 \lstinputlisting[language=c++]{evaluation/cpp-vprint.hpp}2936 2937 \subsubsection{cpp-vbench.cpp} ~2938 2939 \lstinputlisting[language=c++]{evaluation/cpp-vbench.cpp}2940 \end{comment}2941 2942 2961 \end{document} 2943 2962 -
doc/papers/general/evaluation/Makefile
rb2e8841 rf4abc58 2 2 CFA = cfa 3 3 DEPFLAGS = -MMD -MP 4 ifdef DBG 5 CFLAGS = -O0 -ggdb -DN=500 6 else 4 7 CFLAGS = -O2 5 8 ifdef N 6 9 CFLAGS += -DN=$(N) 10 endif 7 11 endif 8 12 CXXFLAGS = $(CFLAGS) --std=c++14 … … 27 31 $(COMPILE.cfa) $(OUTPUT_OPTION) -c $< 28 32 29 COBJS = c-stack.o c-pair.o c- print.o c-bench.o33 COBJS = c-stack.o c-pair.o c-bench.o 30 34 CPPOBJS = cpp-bench.o 31 35 CPPVOBJS = cpp-vstack.o cpp-vbench.o 32 CFAOBJS = cfa-stack.o cfa-pair.o cfa- print.o cfa-bench.o36 CFAOBJS = cfa-stack.o cfa-pair.o cfa-bench.o 33 37 34 38 ${COBJS} ${CPPOBJS} ${CPPVOBJS} ${CFAOBJS} : ${MAKEFILE_NAME} 35 39 36 40 CFILES = bench.h $(patsubst c-bench.h,,$(COBJS:.o=.h)) $(COBJS:.o=.c) 37 CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp cpp-print.hpp$(CPPOBJS:.o=.cpp)38 CPPVFILES = bench.hpp object.hpp cpp-vprint.hpp$(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp)41 CPPFILES = bench.hpp cpp-stack.hpp cpp-pair.hpp $(CPPOBJS:.o=.cpp) 42 CPPVFILES = bench.hpp object.hpp $(patsubst cpp-vbench.hpp,,$(CPPVOBJS:.o=.hpp)) $(CPPVOBJS:.o=.cpp) 39 43 CFAFILES = bench.h $(patsubst cfa-bench.h,,$(CFAOBJS:.o=.h)) $(CFAOBJS:.o=.c) 40 44 -
doc/papers/general/evaluation/bench.h
rb2e8841 rf4abc58 5 5 long ms_between(clock_t start, clock_t end) { return (end - start) / (CLOCKS_PER_SEC / 1000); } 6 6 7 #ifndef N 7 8 #define N 40000000 9 #endif 10 8 11 #define TIMED(name, code) { \ 9 12 volatile clock_t _start, _end; \ -
doc/papers/general/evaluation/bench.hpp
rb2e8841 rf4abc58 6 6 long ms_between(clock_t start, clock_t end) { return (end - start) / (CLOCKS_PER_SEC / 1000); } 7 7 8 #ifndef N 8 9 static const int N = 40000000; 10 #endif 11 9 12 #define TIMED(name, code) { \ 10 13 volatile clock_t _start, _end; \ -
doc/papers/general/evaluation/c-bench.c
rb2e8841 rf4abc58 4 4 #include "c-pair.h" 5 5 #include "c-stack.h" 6 #include "c-print.h"7 6 8 7 _Bool* new_bool( _Bool b ) { … … 39 38 40 39 int main(int argc, char** argv) { 41 FILE * out = fopen("/dev/null", "w");42 40 int maxi = 0, vali = 42; 43 41 struct stack si = new_stack(), ti; … … 50 48 if ( *xi > maxi ) { maxi = *xi; } 51 49 free(xi); ) 52 REPEAT_TIMED( "print_int", N/2, print( out, "dsds", vali, ":", vali, "\n" ); /***/ )53 50 54 51 struct pair * maxp = new_pair( new_bool(0), new_char('\0') ), … … 67 64 free_pair_bool_char( xp ); /***/ 68 65 } ) 69 REPEAT_TIMED( "print_pair", N/2, print( out, "pbcspbcs", *valp, ":", *valp, "\n" ); /***/ )70 66 free_pair_bool_char( maxp ); /***/ 71 67 free_pair_bool_char( valp ); /***/ 72 fclose(out);73 68 } -
doc/papers/general/evaluation/cfa-bench.c
rb2e8841 rf4abc58 1 #include <fstream>2 #include <stdlib>3 1 #include "bench.h" 4 2 #include "cfa-stack.h" 5 3 #include "cfa-pair.h" 6 #include "cfa-print.h"7 4 8 5 int main( int argc, char * argv[] ) { 9 ofstream out = { "/dev/null" };10 6 int max = 0, val = 42; 11 stack( int ) si, t ;7 stack( int ) si, ti; 12 8 13 9 REPEAT_TIMED( "push_int", N, push( si, val ); ) 14 TIMED( "copy_int", t = si; )10 TIMED( "copy_int", ti = si; ) 15 11 TIMED( "clear_int", clear( si ); ) 16 REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); )17 REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )12 REPEAT_TIMED( "pop_int", N, 13 int x = pop( ti ); if ( x > max ) max = x; ) 18 14 19 pair( _Bool, char ) max = { (_Bool)0 , '\0' }, val = { (_Bool)1, 'a' };20 stack( pair( _Bool, char ) ) s , t;15 pair( _Bool, char ) max = { (_Bool)0 /***/, '\0' }, val = { (_Bool)1 /***/, 'a' }; 16 stack( pair( _Bool, char ) ) sp, tp; 21 17 22 REPEAT_TIMED( "push_pair", N, push( s , val ); )23 TIMED( "copy_pair", t = s; )24 TIMED( "clear_pair", clear( s ); )25 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); )26 REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )18 REPEAT_TIMED( "push_pair", N, push( sp, val ); ) 19 TIMED( "copy_pair", tp = sp; ) 20 TIMED( "clear_pair", clear( sp ); ) 21 REPEAT_TIMED( "pop_pair", N, 22 pair(_Bool, char) x = pop( tp ); if ( x > max ) max = x; ) 27 23 } -
doc/papers/general/evaluation/cfa-pair.c
rb2e8841 rf4abc58 36 36 } 37 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 } // ?|?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
rb2e8841 rf4abc58 30 30 int ?>=?(pair(R, S) p, pair(R, S) q); 31 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) );32 // forall(otype R, otype S) 33 // forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S ); }) 34 // ostype & ?|?( ostype & os, pair(R, S) ); -
doc/papers/general/evaluation/cfa-stack.c
rb2e8841 rf4abc58 6 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 }12 8 13 9 forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; } … … 16 12 stack_node(T) ** crnt = &s.head; 17 13 for ( stack_node(T) * next = t.head; next; next = next->next ) { 18 // *crnt = new( next->value, (stack_node(T)*)0 ); 19 stack_node(T)* new_node = ((stack_node(T)*)malloc()); 20 (*new_node){ next->value }; /***/ 14 stack_node(T)* new_node = (stack_node(T)*)malloc(); /***/ 15 (*new_node){ next->value }; 21 16 *crnt = new_node; 22 stack_node(T) * acrnt = *crnt; 23 crnt = &acrnt->next; 17 crnt = &(*crnt)->next; 24 18 } 25 19 *crnt = 0; … … 38 32 39 33 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 }; /***/ 34 stack_node(T)* new_node = (stack_node(T)*)malloc(); /***/ 35 (*new_node){ value, s.head }; 43 36 s.head = new_node; 44 37 } … … 48 41 s.head = n->next; 49 42 T v = n->value; 50 delete( n ); 43 ^(*n){}; 44 free( n ); 51 45 return v; 52 46 } … … 56 50 stack_node(T) * crnt = next; 57 51 next = crnt->next; 58 delete( crnt ); 52 ^(*crnt){}; 53 free(crnt); 59 54 } 60 55 s.head = 0; -
doc/papers/general/evaluation/cpp-bench.cpp
rb2e8841 rf4abc58 1 1 #include <algorithm> 2 #include <fstream>3 2 #include "bench.hpp" 4 3 #include "cpp-stack.hpp" 5 4 #include "cpp-pair.hpp" 6 #include "cpp-print.hpp"7 5 8 6 int main(int argc, char** argv) { 9 std::ofstream out{"/dev/null"};10 7 int maxi = 0, vali = 42; 11 8 stack<int> si, ti; … … 15 12 TIMED( "clear_int", si.clear(); ) 16 13 REPEAT_TIMED( "pop_int", N, maxi = std::max( maxi, ti.pop() ); ) 17 REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); )18 14 19 15 pair<bool, char> maxp = { false, '\0' }, valp = { true, 'a' }; … … 24 20 TIMED( "clear_pair", sp.clear(); ) 25 21 REPEAT_TIMED( "pop_pair", N, maxp = std::max( maxp, tp.pop() ); ) 26 REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); )27 22 } -
doc/papers/general/evaluation/cpp-vbench.cpp
rb2e8841 rf4abc58 1 1 #include <algorithm> 2 #include <fstream>3 2 #include "bench.hpp" 4 3 #include "cpp-vstack.hpp" 5 #include "cpp-vprint.hpp"6 4 #include "object.hpp" 7 5 8 6 int main(int argc, char** argv) { 9 std::ofstream out{"/dev/null"};10 7 integer maxi{ 0 }, vali{ 42 }; 11 8 stack si, ti; … … 15 12 TIMED( "clear_int", si.clear(); ) 16 13 REPEAT_TIMED( "pop_int", N, maxi = std::max( maxi, ti.pop()->as<integer>() ); /***/ ) 17 REPEAT_TIMED( "print_int", N/2, print( out, vali, c_string{":"}, vali, c_string{"\n"} ); )18 14 19 15 ptr<pair> maxp = make<pair>( make<boolean>(false), make<character>('\0') ); … … 27 23 ptr<pair> xp = as_ptr<pair>( tp.pop() ); /***/ 28 24 if ( *xp > *maxp ) { maxp = std::move(xp); } ) 29 REPEAT_TIMED( "print_pair", N/2, print( out, valp, c_string{":"}, valp, c_string{"\n"} ); )30 25 } -
doc/papers/general/evaluation/timing.dat
rb2e8841 rf4abc58 1 1 "400 million repetitions" "C" "\\CFA{}" "\\CC{}" "\\CC{obj}" 2 "push\nint" 3002 2459 1520 3305 3 "copy\nint" 2985 2057 1521 3152 4 "clear\nint" 1374 827 718 1469 5 "pop\nint" 1416 1221 717 5467 6 "print\nint" 5656 6758 3120 3121 7 "push\npair" 4214 2752 946 6826 8 "copy\npair" 6127 2105 993 7330 9 "clear\npair" 2881 885 711 3564 10 "pop\npair" 3046 5434 783 26538 11 "print\npair" 7514 10714 8717 16525 2 "push\nint" 2976 2225 1522 3266 3 "copy\nnt" 2932 7072 1526 3110 4 "clear\nint" 1380 731 750 1488 5 "pop\nint" 1444 1196 756 5156 6 "push\npair" 3695 2257 953 6840 7 "copy\npair" 6034 6650 994 7224 8 "clear\npair" 2832 848 742 3297 9 "pop\npair" 3009 5348 797 25235 10 -
src/Common/SemanticError.h
rb2e8841 rf4abc58 72 72 } 73 73 74 75 76 77 74 // Local Variables: // 78 75 // tab-width: 4 // -
src/Parser/ExpressionNode.cc
rb2e8841 rf4abc58 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
rb2e8841 rf4abc58 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/libcfa/concurrency/kernel
rb2e8841 rf4abc58 79 79 80 80 // Processor 81 coroutine processorCtx_t { 82 struct processor * proc; 83 }; 84 81 85 // Wrapper around kernel threads 82 86 struct processor { 83 87 // Main state 84 88 // Coroutine ctx who does keeps the state of the processor 85 struct processorCtx_t *runner;89 struct processorCtx_t runner; 86 90 87 91 // Cluster from which to get threads -
src/libcfa/concurrency/kernel.c
rb2e8841 rf4abc58 124 124 //----------------------------------------------------------------------------- 125 125 // Processor coroutine 126 void ?{}(processorCtx_t & this) {} 126 127 127 128 // Construct the processor context of the main processor … … 130 131 this.__cor.starter = NULL; 131 132 this.proc = proc; 132 proc->runner = &this;133 133 } 134 134 … … 137 137 (this.__cor){ info }; 138 138 this.proc = proc; 139 proc->runner = &this;140 139 } 141 140 … … 150 149 preemption_alarm = NULL; 151 150 pending_preemption = false; 151 runner.proc = &this; 152 152 153 153 start( &this ); … … 161 161 pending_preemption = false; 162 162 kernel_thread = pthread_self(); 163 164 this.runner = &runner; 163 runner.proc = &this; 164 165 165 __cfaabi_dbg_print_safe("Kernel : constructing main processor context %p\n", &runner); 166 166 runner{ &this }; … … 196 196 void main(processorCtx_t & runner) { 197 197 processor * this = runner.proc; 198 verify(this); 198 199 199 200 __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this); … … 241 242 void runThread(processor * this, thread_desc * dst) { 242 243 assert(dst->curr_cor); 243 coroutine_desc * proc_cor = get_coroutine( *this->runner);244 coroutine_desc * proc_cor = get_coroutine(this->runner); 244 245 coroutine_desc * thrd_cor = dst->curr_cor; 245 246 … … 256 257 257 258 void returnToKernel() { 258 coroutine_desc * proc_cor = get_coroutine( *this_processor->runner);259 coroutine_desc * proc_cor = get_coroutine(this_processor->runner); 259 260 coroutine_desc * thrd_cor = this_thread->curr_cor = this_coroutine; 260 261 ThreadCtxSwitch(thrd_cor, proc_cor); … … 317 318 machine_context_t ctx; 318 319 info.context = &ctx; 319 processorCtx_t proc_cor_storage ={ proc, &info };320 321 __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", proc_cor_storage.__cor.stack.base);320 (proc->runner){ proc, &info }; 321 322 __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.base); 322 323 323 324 //Set global state 324 this_coroutine = &proc->runner->__cor;325 this_coroutine = get_coroutine(proc->runner); 325 326 this_thread = NULL; 326 327 327 328 //We now have a proper context from which to schedule threads 328 __cfaabi_dbg_print_safe("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);329 __cfaabi_dbg_print_safe("Kernel : core %p created (%p, %p)\n", proc, &proc->runner, &ctx); 329 330 330 331 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't … … 332 333 // back to here. Instead directly call the main since we already are on the 333 334 // appropriate stack. 334 proc_cor_storage.__cor.state = Active;335 main( proc _cor_storage);336 proc_cor_storage.__cor.state = Halted;335 get_coroutine(proc->runner)->state = Active; 336 main( proc->runner ); 337 get_coroutine(proc->runner)->state = Halted; 337 338 338 339 // Main routine of the core returned, the core is now fully terminated 339 __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, proc->runner);340 __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner); 340 341 341 342 return NULL; … … 352 353 void kernel_first_resume(processor * this) { 353 354 coroutine_desc * src = this_coroutine; 354 coroutine_desc * dst = get_coroutine( *this->runner);355 coroutine_desc * dst = get_coroutine(this->runner); 355 356 356 357 verify( !preemption_state.enabled ); 357 358 358 359 create_stack(&dst->stack, dst->stack.size); 359 CtxStart( this->runner, CtxInvokeCoroutine);360 CtxStart(&this->runner, CtxInvokeCoroutine); 360 361 361 362 verify( !preemption_state.enabled ); … … 411 412 verify( !preemption_state.enabled ); 412 413 lock( ready_queue_lock __cfaabi_dbg_ctx2 ); 413 //TEMP hack to find a bug414 if(this_processor != mainProcessor) {415 if(ready_queue.head == mainThread) {416 unlock( ready_queue_lock );417 return NULL;418 }419 }420 421 414 thread_desc * head = pop_head( ready_queue ); 422 415 unlock( ready_queue_lock ); … … 584 577 // Destroy the main processor and its context in reverse order of construction 585 578 // These were manually constructed so we need manually destroy them 586 ^( *mainProcessor->runner){};579 ^(mainProcessor->runner){}; 587 580 ^(mainProcessor){}; 588 581 -
src/libcfa/concurrency/kernel_private.h
rb2e8841 rf4abc58 52 52 //----------------------------------------------------------------------------- 53 53 // Processor 54 coroutine processorCtx_t {55 processor * proc;56 };57 58 54 void main(processorCtx_t *); 59 55 void start(processor * this); -
src/tests/.expect/literals.x64.txt
rb2e8841 rf4abc58 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/literals.x86.txt
rb2e8841 rf4abc58 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 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 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 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 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 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 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
rb2e8841 rf4abc58 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
rb2e8841 rf4abc58 123 123 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 124 124 125 # Warnings 125 126 warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@ 126 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@} 127 echo > ${@} 127 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only -
src/tests/Makefile.in
rb2e8841 rf4abc58 800 800 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 801 801 802 # Warnings 802 803 warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@ 803 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@} 804 echo > ${@} 804 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only 805 805 806 806 # Tell versions [3.59,3.63) of GNU make to not export all variables. -
src/tests/literals.c
rb2e8841 rf4abc58 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
rb2e8841 rf4abc58 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 -
src/tests/warnings/.expect/self-assignment.txt
rb2e8841 rf4abc58 1 warnings/self-assignment.c:29:1 warning: self assignment of expression: Cast of: 2 Variable Expression: j: signed int 3 ... to: 4 reference to signed int 5 warnings/self-assignment.c:30:1 warning: self assignment of expression: Cast of: 6 Variable Expression: s: instance of struct S with body 1 7 ... to: 8 reference to instance of struct S with body 1 9 warnings/self-assignment.c:31:1 warning: self assignment of expression: Cast of: 10 Member Expression, with field: 11 i: signed int 12 ... from aggregate: 13 Variable Expression: s: instance of struct S with body 1 14 ... to: 15 reference to signed int 16 warnings/self-assignment.c:32:1 warning: self assignment of expression: Cast of: 17 Member Expression, with field: 18 i: signed int 19 ... from aggregate: 20 Member Expression, with field: 21 s: instance of struct S with body 1 22 ... from aggregate: 23 Variable Expression: t: instance of struct T with body 1 24 ... to: 25 reference to signed int
Note: See TracChangeset
for help on using the changeset viewer.