Changeset ea46db7
- Timestamp:
- Mar 4, 2018, 12:20:36 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:
- 1feb535f, d893266a
- Parents:
- 0a2168f
- git-author:
- Peter A. Buhr <pabuhr@…> (03/04/18 10:35:22)
- git-committer:
- Peter A. Buhr <pabuhr@…> (03/04/18 12:20:36)
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/papers/general/Paper.tex
r0a2168f rea46db7 990 990 \section{Control Structures} 991 991 992 \CFA identifies missing and problematic control structures in C, and extends and modifies these control structures to increase functionality and safety. 992 \CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds to control structures to increase functionality and safety. 993 994 995 \subsection{\texorpdfstring{\LstKeywordStyle{if} Statement}{if Statement}} 996 997 The @if@ expression allows declarations, similar to @for@ declaration expression: 998 \begin{cfa} 999 if ( int x = f() ) ... $\C{// x != 0}$ 1000 if ( int x = f(), y = g() ) ... $\C{// x != 0 \&\& y != 0}$ 1001 if ( int x = f(), y = g(); `x < y` ) ... $\C{// relational expression}$ 1002 \end{cfa} 1003 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the @if@ expression, and the results are combined using the logical @&&@ operator.\footnote{\CC only provides a single declaration always compared not equal to 0.} 1004 The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses. 1005 1006 1007 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 1008 1009 There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses. 1010 1011 C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}. 1012 \CFA provides a shorthand for a non-contiguous list: 1013 \begin{cquote} 1014 \lstDeleteShortInline@% 1015 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1016 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1017 \begin{cfa} 1018 case 2, 10, 34, 42: 1019 \end{cfa} 1020 & 1021 \begin{cfa} 1022 case 2: case 10: case 34: case 42: 1023 \end{cfa} 1024 \end{tabular} 1025 \lstMakeShortInline@% 1026 \end{cquote} 1027 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1028 \begin{cquote} 1029 \lstDeleteShortInline@% 1030 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1031 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1032 \begin{cfa} 1033 case 2~42: 1034 \end{cfa} 1035 & 1036 \begin{cfa} 1037 case 2: case 3: ... case 41: case 42: 1038 \end{cfa} 1039 \end{tabular} 1040 \lstMakeShortInline@% 1041 \end{cquote} 1042 and a combination: 1043 \begin{cfa} 1044 case -12~-4, -1~5, 14~21, 34~42: 1045 \end{cfa} 1046 1047 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1048 \begin{cfa} 1049 switch ( i ) { 1050 case 0: 1051 for ( int i = 0; i < 10; i += 1 ) { 1052 ... 1053 `case 1:` // no initialization of loop index 1054 ... 1055 } 1056 } 1057 \end{cfa} 1058 \CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality. 1059 1060 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1061 \begin{cfa} 1062 switch ( x ) { 1063 `int y = 1;` $\C{// unreachable initialization}$ 1064 `x = 7;` $\C{// unreachable code without label/branch}$ 1065 case 0: 1066 ... 1067 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1068 z = 2; 1069 case 1: 1070 `x = z;` $\C{// without fall through, z is undefined}$ 1071 } 1072 \end{cfa} 1073 \CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses. 1074 \CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred. 1075 1076 C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through}; 1077 @case@ clauses are made disjoint by the @break@ statement. 1078 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements. 1079 For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}). 1080 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1081 1082 \begin{figure} 1083 \centering 1084 \lstDeleteShortInline@% 1085 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1086 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1087 \begin{cfa} 1088 `choose` ( day ) { 1089 case Mon~Thu: // program 1090 1091 case Fri: // program 1092 wallet += pay; 1093 `fallthrough;` 1094 case Sat: // party 1095 wallet -= party; 1096 1097 case Sun: // rest 1098 1099 default: // error 1100 } 1101 \end{cfa} 1102 & 1103 \begin{cfa} 1104 switch ( day ) { 1105 case Mon: case Tue: case Wed: case Thu: // program 1106 `break;` 1107 case Fri: // program 1108 wallet += pay; 1109 1110 case Sat: // party 1111 wallet -= party; 1112 `break;` 1113 case Sun: // rest 1114 `break;` 1115 default: // error 1116 } 1117 \end{cfa} 1118 \end{tabular} 1119 \lstMakeShortInline@% 1120 \caption{\lstinline|choose| versus \lstinline|switch| Statements} 1121 \label{f:ChooseSwitchStatements} 1122 \end{figure} 1123 1124 \begin{comment} 1125 Forgotten @break@ statements at the end of @switch@ cases are a persistent sort of programmer error in C, and the @break@ statements themselves introduce visual clutter and an un-C-like keyword-based block delimiter. 1126 \CFA addresses this error by introducing a @choose@ statement, which works identically to a @switch@ except that its default end-of-case behaviour is to break rather than to fall through for all non-empty cases. 1127 Since empty cases like @case 7:@ in @case 7: case 11:@ still have fall-through semantics and explicit @break@ is still allowed at the end of a @choose@ case, many idiomatic uses of @switch@ in standard C can be converted to @choose@ statements by simply changing the keyword. 1128 Where fall-through is desired for a non-empty case, it can be specified with the new @fallthrough@ statement, making @choose@ equivalently powerful to @switch@, but more concise in the common case where most non-empty cases end with a @break@ statement, as in the example below: 1129 1130 \begin{cfa} 1131 choose( i ) { 1132 case 2: 1133 printf("even "); 1134 fallthrough; 1135 case 3: case 5: case 7: 1136 printf("small prime\n"); 1137 case 4,6,8,9: 1138 printf("small composite\n"); 1139 case 13~19: 1140 printf("teen\n"); 1141 default: 1142 printf("something else\n"); 1143 } 1144 \end{cfa} 1145 \end{comment} 993 1146 994 1147 … … 1050 1203 } else { 1051 1204 ... goto `LIF`; ... 1052 } `L 3:` ;1205 } `LIF:` ; 1053 1206 } `LS:` ; 1054 1207 } `LC:` ; … … 1100 1253 1101 1254 1102 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}} 1103 1104 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. 1105 1106 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.}. 1107 \CFA provides a shorthand for a non-contiguous list: 1255 \subsection{Exception Handling} 1256 1257 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts. 1258 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}). 1259 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler. 1260 \CFA restricts exception types to those defined by aggregate type @exception@. 1261 The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@). 1262 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation. 1263 If there is no current exception, the reresume/rethrow results in a runtime error. 1264 1265 \begin{figure} 1108 1266 \begin{cquote} 1109 1267 \lstDeleteShortInline@% 1110 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1111 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1112 \begin{cfa} 1113 case 2, 10, 34, 42: 1114 \end{cfa} 1115 & 1116 \begin{cfa} 1117 case 2: case 10: case 34: case 42: 1268 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1269 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\ 1270 \begin{cfa} 1271 `exception R { int fix; };` 1272 void f() { 1273 R r; 1274 ... `resume( r );` ... 1275 ... r.fix // control does return here after handler 1276 } 1277 `try` { 1278 ... f(); ... 1279 } `catchResume( R r )` { 1280 ... r.fix = ...; // return correction to raise 1281 } // dynamic return to _Resume 1282 \end{cfa} 1283 & 1284 \begin{cfa} 1285 `exception T {};` 1286 void f() { 1287 1288 ... `throw( T{} );` ... 1289 // control does NOT return here after handler 1290 } 1291 `try` { 1292 ... f(); ... 1293 } `catch( T t )` { 1294 ... // recover and continue 1295 } // static return to next statement 1118 1296 \end{cfa} 1119 1297 \end{tabular} 1120 1298 \lstMakeShortInline@% 1121 1299 \end{cquote} 1122 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.} 1300 \caption{\CFA Exception Handling} 1301 \label{f:CFAExceptionHandling} 1302 \end{figure} 1303 1304 The set of exception types in a list of catch clause may include both a resumption and termination handler: 1305 \begin{cfa} 1306 try { 1307 ... resume( `R{}` ); ... 1308 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$ 1309 catch( `R` r ) { ... } $\C{\color{red}// H2}$ 1310 1311 \end{cfa} 1312 The resumption propagation raises @R@ and the stack is not unwound; 1313 the exception is caught by the @catchResume@ clause and handler H1 is invoked. 1314 The termination propagation in handler H1 raises @R@ and the stack is unwound; 1315 the exception is caught by the @catch@ clause and handler H2 is invoked. 1316 The termination handler is available because the resumption propagation did not unwind the stack. 1317 1318 An additional feature is conditional matching in a catch clause: 1319 \begin{cfa} 1320 try { 1321 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$ 1322 ... write( `logfile`, ... ); ... 1323 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$ 1324 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$ 1325 catch ( IOError err ) { ... } $\C{// handler error from other files}$ 1326 \end{cfa} 1327 where the throw inserts the failing file-handle in the I/O exception. 1328 Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible.. 1329 1330 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}: 1331 \begin{cfa} 1332 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ ) 1333 resume( $\emph{alternate-stack}$ ) 1334 \end{cfa} 1335 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}. 1336 Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns. 1337 1338 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation. 1339 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks: 1123 1340 \begin{cquote} 1124 1341 \lstDeleteShortInline@% 1125 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 1126 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1127 \begin{cfa} 1128 case 2~42: 1129 \end{cfa} 1130 & 1131 \begin{cfa} 1132 case 2: case 3: ... case 41: case 42: 1342 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1343 \begin{cfa} 1344 enable $\emph{exception-type-list}$ { 1345 // allow non-local resumption 1346 } 1347 \end{cfa} 1348 & 1349 \begin{cfa} 1350 disable $\emph{exception-type-list}$ { 1351 // disallow non-local resumption 1352 } 1133 1353 \end{cfa} 1134 1354 \end{tabular} 1135 1355 \lstMakeShortInline@% 1136 1356 \end{cquote} 1137 and a combination: 1138 \begin{cfa} 1139 case -12~-4, -1~5, 14~21, 34~42: 1140 \end{cfa} 1141 1142 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83}); 1143 \begin{cfa} 1144 switch ( i ) { 1145 case 0: 1146 for ( int i = 0; i < 10; i += 1 ) { 1147 ... 1148 `case 1:` // no initialization of loop index 1149 ... 1150 } 1151 } 1152 \end{cfa} 1153 \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. 1154 1155 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour: 1156 \begin{cfa} 1157 switch ( x ) { 1158 `int y = 1;` $\C{// unreachable initialization}$ 1159 `x = 7;` $\C{// unreachable code without label/branch}$ 1160 case 0: 1161 ... 1162 `int z = 0;` $\C{// unreachable initialization, cannot appear after case}$ 1163 z = 2; 1164 case 1: 1165 `x = z;` $\C{// without fall through, z is undefined}$ 1166 } 1167 \end{cfa} 1168 \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. 1169 \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. 1170 1171 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}; 1172 @case@ clauses are made disjoint by the @break@ statement. 1173 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. 1174 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}). 1175 Collectively, these enhancements reduce programmer burden and increase readability and safety. 1176 1177 \begin{figure} 1178 \centering 1179 \lstDeleteShortInline@% 1180 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}} 1181 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 1182 \begin{cfa} 1183 `choose` ( day ) { 1184 case Mon~Thu: // program 1185 1186 case Fri: // program 1187 wallet += pay; 1188 `fallthrough;` 1189 case Sat: // party 1190 wallet -= party; 1191 1192 case Sun: // rest 1193 1194 default: // error 1195 } 1196 \end{cfa} 1197 & 1198 \begin{cfa} 1199 switch ( day ) { 1200 case Mon: case Tue: case Wed: case Thu: // program 1201 `break;` 1202 case Fri: // program 1203 wallet += pay; 1204 1205 case Sat: // party 1206 wallet -= party; 1207 `break;` 1208 case Sun: // rest 1209 `break;` 1210 default: // error 1211 } 1212 \end{cfa} 1213 \end{tabular} 1214 \lstMakeShortInline@% 1215 \caption{\lstinline|choose| versus \lstinline|switch| Statements} 1216 \label{f:ChooseSwitchStatements} 1217 \end{figure} 1218 1219 \begin{comment} 1220 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. 1221 \CFA addresses this error by introducing a @choose@ statement, which works identically to a @switch@ except that its default end-of-case behaviour is to break rather than to fall through for all non-empty cases. 1222 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. 1223 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: 1224 1225 \begin{cfa} 1226 choose( i ) { 1227 case 2: 1228 printf("even "); 1229 fallthrough; 1230 case 3: case 5: case 7: 1231 printf("small prime\n"); 1232 case 4,6,8,9: 1233 printf("small composite\n"); 1234 case 13~19: 1235 printf("teen\n"); 1236 default: 1237 printf("something else\n"); 1238 } 1239 \end{cfa} 1240 \end{comment} 1357 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively. 1358 Specifying no exception type is shorthand for specifying all exception types. 1359 Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state. 1360 1361 Finally, \CFA provides a Java like @finally@ clause after the catch clauses: 1362 \begin{cfa} 1363 try { 1364 ... f(); ... 1365 // catchResume or catch clauses 1366 } `finally` { 1367 // house keeping 1368 } 1369 \end{cfa} 1370 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised. 1371 If an exception is raised and caught, the handler is run before the finally clause. 1372 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated. 1373 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses. 1241 1374 1242 1375 … … 1253 1386 S s, as[10]; 1254 1387 \end{cfa} 1255 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:1388 However, functions manipulating aggregates must repeat the aggregate name to access its containing fields: 1256 1389 \begin{cfa} 1257 1390 void f( S s ) { … … 1271 1404 } 1272 1405 \end{C++} 1273 Object-oriented nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.1406 Object-oriented nesting of member functions in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping. 1274 1407 However, for other aggregate parameters, qualification is necessary: 1275 1408 \begin{cfa} … … 1301 1434 'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$ 1302 1435 \end{cfa} 1303 and may appear as the body of a routine or nested within a routinebody.1436 and may appear as the body of a function or nested within a function body. 1304 1437 Each expression in the expression-list provides a type and object. 1305 1438 The type must be an aggregate type. … … 1328 1461 Qualification or a cast is used to disambiguate. 1329 1462 1330 There is an interesting problem between parameters and the routine@with@, \eg:1463 There is an interesting problem between parameters and the function @with@, \eg: 1331 1464 \begin{cfa} 1332 1465 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ … … 1334 1467 } 1335 1468 \end{cfa} 1336 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the routine@with@.1469 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function @with@. 1337 1470 To solve this problem, parameters are treated like an initialized aggregate: 1338 1471 \begin{cfa} … … 1342 1475 } params; 1343 1476 \end{cfa} 1344 and implicitly opened \emph{after} a routineopen, to give them higher priority:1477 and implicitly opened \emph{after} a function open, to give them higher priority: 1345 1478 \begin{cfa} 1346 1479 void ?{}( S & s, int i ) with ( s ) `with( $\emph{\color{red}params}$ )` { … … 1370 1503 1371 1504 1372 \subsection{Exception Handling}1373 1374 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.1375 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).1376 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.1377 \CFA restricts exception types to those defined by aggregate type @exception@.1378 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@).1379 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.1380 If there is no current exception, the reresume/rethrow results in a runtime error.1381 1382 \begin{figure}1383 \begin{cquote}1384 \lstDeleteShortInline@%1385 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}1386 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}} & \multicolumn{1}{c}{\textbf{Termination}} \\1387 \begin{cfa}1388 `exception R { int fix; };`1389 void f() {1390 R r;1391 ... `resume( r );` ...1392 ... r.fix // control does return here after handler1393 }1394 `try` {1395 ... f(); ...1396 } `catchResume( R r )` {1397 ... r.fix = ...; // return correction to raise1398 } // dynamic return to _Resume1399 \end{cfa}1400 &1401 \begin{cfa}1402 `exception T {};`1403 void f() {1404 1405 ... `throw( T{} );` ...1406 // control does NOT return here after handler1407 }1408 `try` {1409 ... f(); ...1410 } `catch( T t )` {1411 ... // recover and continue1412 } // static return to next statement1413 \end{cfa}1414 \end{tabular}1415 \lstMakeShortInline@%1416 \end{cquote}1417 \caption{\CFA Exception Handling}1418 \label{f:CFAExceptionHandling}1419 \end{figure}1420 1421 The set of exception types in a list of catch clause may include both a resumption and termination handler:1422 \begin{cfa}1423 try {1424 ... resume( `R{}` ); ...1425 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$1426 catch( `R` r ) { ... } $\C{\color{red}// H2}$1427 1428 \end{cfa}1429 The resumption propagation raises @R@ and the stack is not unwound;1430 the exception is caught by the @catchResume@ clause and handler H1 is invoked.1431 The termination propagation in handler H1 raises @R@ and the stack is unwound;1432 the exception is caught by the @catch@ clause and handler H2 is invoked.1433 The termination handler is available because the resumption propagation did not unwind the stack.1434 1435 An additional feature is conditional matching in a catch clause:1436 \begin{cfa}1437 try {1438 ... write( `datafile`, ... ); ... $\C{// may throw IOError}$1439 ... write( `logfile`, ... ); ...1440 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$1441 catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$1442 catch ( IOError err ) { ... } $\C{// handler error from other files}$1443 \end{cfa}1444 where the throw inserts the failing file-handle in the I/O exception.1445 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..1446 1447 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:1448 \begin{cfa}1449 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )1450 resume( $\emph{alternate-stack}$ )1451 \end{cfa}1452 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.1453 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.1454 1455 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.1456 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:1457 \begin{cquote}1458 \lstDeleteShortInline@%1459 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}1460 \begin{cfa}1461 enable $\emph{exception-type-list}$ {1462 // allow non-local resumption1463 }1464 \end{cfa}1465 &1466 \begin{cfa}1467 disable $\emph{exception-type-list}$ {1468 // disallow non-local resumption1469 }1470 \end{cfa}1471 \end{tabular}1472 \lstMakeShortInline@%1473 \end{cquote}1474 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.1475 Specifying no exception type is shorthand for specifying all exception types.1476 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.1477 1478 Finally, \CFA provides a Java like @finally@ clause after the catch clauses:1479 \begin{cfa}1480 try {1481 ... f(); ...1482 // catchResume or catch clauses1483 } `finally` {1484 // house keeping1485 }1486 \end{cfa}1487 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.1488 If an exception is raised and caught, the handler is run before the finally clause.1489 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.1490 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.1491 1492 1493 1505 \section{Declarations} 1494 1506 … … 1518 1530 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers? 1519 1531 If there is any doubt, it implies productivity and safety issues even for basic programs. 1520 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.1521 For example, a routinereturning a pointer to an array of integers is defined and used in the following way:1532 Another example of confusion results from the fact that a function name and its parameters are embedded within the return type, mimicking the way the return value is used at the function's call site. 1533 For example, a function returning a pointer to an array of integers is defined and used in the following way: 1522 1534 \begin{cfa} 1523 1535 int `(*`f`())[`5`]` {...}; $\C{// definition}$ 1524 1536 ... `(*`f`())[`3`]` += 1; $\C{// usage}$ 1525 1537 \end{cfa} 1526 Essentially, the return type is wrapped around the routinename in successive layers (like an onion).1538 Essentially, the return type is wrapped around the function name in successive layers (like an onion). 1527 1539 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice. 1528 1540 1529 \CFA provides its own type, variable and routinedeclarations, using a different syntax.1541 \CFA provides its own type, variable and function declarations, using a different syntax. 1530 1542 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right. 1531 1543 The qualifiers have the same meaning but are ordered left to right to specify a variable's type. … … 1555 1567 \end{cquote} 1556 1568 The only exception is bit field specification, which always appear to the right of the base type. 1557 % Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a routineparameter.1569 % Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a function parameter. 1558 1570 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list. 1559 1571 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows: … … 1641 1653 \lstMakeShortInline@% 1642 1654 \end{cquote} 1643 Specifiers must appear at the start of a \CFA routinedeclaration\footnote{\label{StorageClassSpecifier}1655 Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier} 1644 1656 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}}. 1645 1657 1646 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo- routine@sizeof@:1658 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@: 1647 1659 \begin{cquote} 1648 1660 \lstDeleteShortInline@% … … 1662 1674 \end{cquote} 1663 1675 1664 The syntax of the new routine prototype declaration follows directly from the new routinedefinition syntax;1676 The syntax of the new function-prototype declaration follows directly from the new function-definition syntax; 1665 1677 as well, parameter names are optional, \eg: 1666 1678 \begin{cfa} … … 1671 1683 [ * int, int ] j ( int ); $\C{// returning pointer to int and int, with int parameter}$ 1672 1684 \end{cfa} 1673 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routinedefinition header (or vice versa).1674 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routinenames in the declaration list, \eg:1685 This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa). 1686 Like C, it is possible to declare multiple function-prototypes in a single declaration, where the return type is distributed across \emph{all} function names in the declaration list, \eg: 1675 1687 \begin{cquote} 1676 1688 \lstDeleteShortInline@% … … 1687 1699 \lstMakeShortInline@% 1688 1700 \end{cquote} 1689 where \CFA allows the last routinein the list to define its body.1690 1691 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:1692 \begin{cfa} 1693 * [ int x ] () fp; $\C{// pointer to routinereturning int with no parameters}$1694 * [ * int ] ( int y ) gp; $\C{// pointer to routinereturning pointer to int with int parameter}$1695 * [ ] ( int, char ) hp; $\C{// pointer to routinereturning no result with int and char parameters}$1696 * [ * int, int ] ( int ) jp; $\C{// pointer to routinereturning pointer to int and int, with int parameter}$1697 \end{cfa} 1698 Note, a routinename cannot be specified:1699 \begin{cfa} 1700 * [ int x ] f () fp; $\C{// routinename "f" is disallowed}$1701 where \CFA allows the last function in the list to define its body. 1702 1703 The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg: 1704 \begin{cfa} 1705 * [ int x ] () fp; $\C{// pointer to function returning int with no parameters}$ 1706 * [ * int ] ( int y ) gp; $\C{// pointer to function returning pointer to int with int parameter}$ 1707 * [ ] ( int, char ) hp; $\C{// pointer to function returning no result with int and char parameters}$ 1708 * [ * int, int ] ( int ) jp; $\C{// pointer to function returning pointer to int and int, with int parameter}$ 1709 \end{cfa} 1710 Note, a function name cannot be specified: 1711 \begin{cfa} 1712 * [ int x ] f () fp; $\C{// function name "f" is disallowed}$ 1701 1713 \end{cfa} 1702 1714 … … 1918 1930 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}. 1919 1931 \begin{cfa} 1920 struct VLA { 1921 int len, * data; 1922 }; 1923 void ?{}( VLA & vla ) with ( vla ) { $\C{// default constructor}$ 1924 len = 10; data = alloc( len ); $\C{// shallow copy}$ 1925 } 1926 void ^?{}( VLA & vla ) with ( vla ) { $\C{// destructor}$ 1927 free( data ); 1928 } 1932 struct VLA { int len, * data; }; 1933 void ?{}( VLA & vla ) with ( vla ) { len = 10; data = alloc( len ); } $\C{// default constructor}$ 1934 void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$ 1929 1935 { 1930 1936 VLA x; $\C{// implicit: ?\{\}( x );}$ 1931 1937 } $\C{// implicit: ?\^{}\{\}( x );}$ 1932 1938 \end{cfa} 1933 (Note, the example is purposely kept simple by using shallow-copy semantics.)1934 1939 @VLA@ is a \newterm{managed type}\footnote{ 1935 1940 A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a field of a managed type. … … 1939 1944 \CFA also provides syntax for \newterm{initialization} and \newterm{copy}: 1940 1945 \begin{cfa} 1941 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { 1946 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { $\C{// initialization}$ 1942 1947 len = size; data = alloc( len, fill ); 1943 1948 } 1944 void ?{}( VLA & vla, VLA other ) { $\C{// copy }$1949 void ?{}( VLA & vla, VLA other ) { $\C{// copy, shallow}$ 1945 1950 vla.len = other.len; vla.data = other.data; 1946 1951 } 1947 1952 \end{cfa} 1953 (Note, the example is purposely kept simple by using shallow-copy semantics.) 1948 1954 An initialization constructor-call has the same syntax as a C initializer, except the initialization values are passed as arguments to a matching constructor (number and type of paremeters). 1949 1955 \begin{cfa} … … 1959 1965 \begin{cfa} 1960 1966 { 1961 VLA x, y = { 20, 0x01 }, z = y;1962 // implicit: ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); z points to y1967 VLA x, y = { 20, 0x01 }, z = y; $\C{// z points to y}$ 1968 // ?{}( x ); ?{}( y, 20, 0x01 ); ?{}( z, y ); 1963 1969 ^x{}; $\C{// deallocate x}$ 1964 1970 x{}; $\C{// reallocate x}$ … … 1967 1973 y{ x }; $\C{// reallocate y, points to x}$ 1968 1974 x{}; $\C{// reallocate x, not pointing to y}$ 1969 // implicit:^?{}(z); ^?{}(y); ^?{}(x);1975 // ^?{}(z); ^?{}(y); ^?{}(x); 1970 1976 } 1971 1977 \end{cfa} … … 1998 2004 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix. 1999 2005 In keeping with the general \CFA approach of adding features while respecting the ``C-style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backwards-compatible semantics. 2000 A trivial example is allowing the underscore to separate prefixes, digits, and suffixes in all \CFA constants, as in Ada, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@. 2006 A trivial example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@. 2007 2008 2009 \subsection{Integral Suffixes} 2010 2011 Additional integral suffixes are added to cover all the integral types and lengths. 2012 \begin{cquote} 2013 \lstDeleteShortInline@% 2014 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2015 \begin{cfa} 2016 20`_hh` // signed char 2017 21`_hhu` // unsigned char 2018 22`_h` // signed short int 2019 23`_uh` // unsigned short int 2020 24`z` // size_t 2021 \end{cfa} 2022 & 2023 \begin{cfa} 2024 20`_L8` // int8_t 2025 21`_ul8` // uint8_t 2026 22`_l16` // int16_t 2027 23`_ul16` // uint16_t 2028 24`_l32` // int32_t 2029 \end{cfa} 2030 & 2031 \begin{cfa} 2032 25`_ul32` // uint32_t 2033 26`_l64` // int64_t 2034 27`_l64u` // uint64_t 2035 26`_L128` // int128 2036 27`_L128u` // unsigned int128 2037 \end{cfa} 2038 \end{tabular} 2039 \lstMakeShortInline@% 2040 \end{cquote} 2001 2041 2002 2042 … … 2015 2055 2016 2056 2017 \subsection{Integral Suffixes} 2018 2019 Additional integral suffixes are added to cover all the integral types and lengths. 2020 \begin{cquote} 2057 \subsection{User Literals} 2058 2059 For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours). 2060 The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call-syntax (literal argument before function name), using the backquote, to convert basic literals into user literals. 2061 The backquote is a small character, making the unit (function name) predominate. 2062 For examples, the multi-precision integers in Section~\ref{s:MultiPrecisionIntegers} make use of user literals: 2063 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2064 \begin{cfa} 2065 y = 9223372036854775807L|`mp| * 18446744073709551615UL|`mp|; 2066 y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|; 2067 \end{cfa} 2068 Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions. 2069 }% 2070 2071 The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax. 2072 However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals. 2073 After which, user literals must match (no conversions); 2074 hence, it is necessary to overload the unit with all appropriate types. 2075 Finally, the use of the single quote as a separator is restricted to digits, precluding its use in the literal prefix or suffix, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote. 2076 2077 \begin{figure} 2078 \centering 2079 \lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2021 2080 \lstDeleteShortInline@% 2022 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 2023 \begin{cfa} 2024 20`_hh` // signed char 2025 21`_hhu` // unsigned char 2026 22`_h` // signed short int 2027 23`_uh` // unsigned short int 2028 24`z` // size_t 2029 \end{cfa} 2030 & 2031 \begin{cfa} 2032 20`_L8` // int8_t 2033 21`_ul8` // uint8_t 2034 22`_l16` // int16_t 2035 23`_ul16` // uint16_t 2036 24`_l32` // int32_t 2037 \end{cfa} 2038 & 2039 \begin{cfa} 2040 25`_ul32` // uint32_t 2041 26`_l64` // int64_t 2042 27`_l64u` // uint64_t 2043 26`_L128` // int128 2044 27`_L128u` // unsigned int128 2081 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2082 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\ 2083 \begin{cfa} 2084 struct W { 2085 double stones; 2086 }; 2087 void ?{}( W & w ) { w.stones = 0; } 2088 void ?{}( W & w, double w ) { w.stones = w; } 2089 W ?+?( W l, W r ) { 2090 return (W){ l.stones + r.stones }; 2091 } 2092 W |?`st|( double w ) { return (W){ w }; } 2093 W |?`lb|( double w ) { return (W){ w / 14.0 }; } 2094 W |?`kg|( double w ) { return (W) { w * 0.16 }; } 2095 2096 2097 2098 int main() { 2099 W w, heavy = { 20 }; 2100 w = 155|`lb|; 2101 w = 0b_1111|`st|; 2102 w = 0_233|`lb|; 2103 w = 0x_9b_u|`kg|; 2104 w = 5.5|`st| + 8|`kg| + 25.01|`lb| + heavy; 2105 } 2106 \end{cfa} 2107 & 2108 \begin{cfa} 2109 struct W { 2110 double stones; 2111 W() { stones = 0.0; } 2112 W( double w ) { stones = w; } 2113 }; 2114 W operator+( W l, W r ) { 2115 return W( l.stones + r.stones ); 2116 } 2117 W |operator"" _st|( unsigned long long int w ) { return W( w ); } 2118 W |operator"" _lb|( unsigned long long int w ) { return W( w / 14.0 ); } 2119 W |operator"" _kg|( unsigned long long int w ) { return W( w * 0.16 ); } 2120 W |operator"" _st|( long double w ) { return W( w ); } 2121 W |operator"" _lb|( long double w ) { return W( w / 14.0 ); } 2122 W |operator"" _kg|( long double w ) { return W( w * 0.16 ); } 2123 int main() { 2124 W w, heavy = { 20 }; 2125 w = 155|_lb|; 2126 w = 0b1111|_lb|; // error, binary unsupported 2127 w = 0${\color{red}'}$233|_lb|; // quote separator 2128 w = 0x9b|_kg|; 2129 w = 5.5d|_st| + 8|_kg| + 25.01|_lb| + heavy; 2130 } 2045 2131 \end{cfa} 2046 2132 \end{tabular} 2047 2133 \lstMakeShortInline@% 2048 \end{cquote} 2049 2050 2051 \subsection{Units} 2052 2053 Alternative call syntax (literal argument before routine name) to convert basic literals into user literals. 2054 2055 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}} 2056 \begin{cfa} 2057 struct Weight { double stones; }; 2058 void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$ 2059 void ?{}( Weight & w, double w ) { w.stones = w; } 2060 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } 2061 2062 Weight |?`st|( double w ) { return (Weight){ w }; } $\C{// backquote for units}$ 2063 Weight |?`lb|( double w ) { return (Weight){ w / 14.0 }; } 2064 Weight |?`kg|( double w ) { return (Weight) { w * 0.1575}; } 2065 2066 int main() { 2067 Weight w, heavy = { 20 }; $\C{// 20 stone}$ 2068 w = 155|`lb|; 2069 w = 0x_9b_u|`lb|; $\C{// hexadecimal unsigned weight (155)}$ 2070 w = 0_233|`lb|; $\C{// octal weight (155)}$ 2071 w = 5|`st| + 8|`kg| + 25|`lb| + heavy; 2072 } 2073 \end{cfa} 2074 }% 2134 \caption{User Literal} 2135 \label{f:UserLiteral} 2136 \end{figure} 2075 2137 2076 2138 … … 2082 2144 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime. 2083 2145 The following sections give a glimpse of the interface reduction to many C libraries. 2084 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.2146 In many cases, @signed@/@unsigned@ @char@, @short@, and @_Complex@ functions are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results. 2085 2147 2086 2148 … … 2110 2172 \begin{cquote} 2111 2173 \lstDeleteShortInline@% 2112 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2113 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2174 \lstset{basicstyle=\linespread{0.9}\sf\small} 2175 \begin{tabular}{@{}l@{\hspace{0.5\parindentlnth}}l@{}} 2176 \multicolumn{1}{c@{\hspace{0.5\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2114 2177 \begin{cfa} 2115 2178 MIN 2116 2117 2179 MAX 2118 2119 2180 PI 2120 2181 E … … 2122 2183 & 2123 2184 \begin{cfa} 2124 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, 2125 FLT_MIN, DBL_MIN, LDBL_MIN 2126 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, 2127 FLT_MAX, DBL_MAX, LDBL_MAX 2185 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN 2186 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX 2128 2187 M_PI, M_PIl 2129 2188 M_E, M_El … … 2136 2195 \subsection{Math} 2137 2196 2138 C library @math.h@ provides many mathematical routines.2139 \CFA routine overloading is used to condense these mathematical routines, \eg:2197 C library @math.h@ provides many mathematical functions. 2198 \CFA function overloading is used to condense these mathematical functions, \eg: 2140 2199 \begin{cquote} 2141 2200 \lstDeleteShortInline@% … … 2156 2215 \lstMakeShortInline@% 2157 2216 \end{cquote} 2158 The result is a significant reduction in names to access math routines, \eg:2217 The result is a significant reduction in names to access math functions, \eg: 2159 2218 \begin{cquote} 2160 2219 \lstDeleteShortInline@% … … 2175 2234 \lstMakeShortInline@% 2176 2235 \end{cquote} 2177 While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a routinename with a single set of floating type(s).2236 While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a function name with a single set of floating type(s). 2178 2237 For example, it is impossible to overload @atan@ for both one and two arguments; 2179 2238 instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}). 2180 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.2239 The key observation is that only a restricted set of type-generic macros are provided for a limited set of function names, which do not generalize across the type system, as in \CFA. 2181 2240 2182 2241 2183 2242 \subsection{Standard} 2184 2243 2185 C library @stdlib.h@ provides many general routines.2186 \CFA routine overloading is used to condense these utility routines, \eg:2244 C library @stdlib.h@ provides many general functions. 2245 \CFA function overloading is used to condense these utility functions, \eg: 2187 2246 \begin{cquote} 2188 2247 \lstDeleteShortInline@% … … 2203 2262 \lstMakeShortInline@% 2204 2263 \end{cquote} 2205 The result is a significant reduction in names to access utility routines, \eg:2264 The result is a significant reduction in names to access utility functions, \eg: 2206 2265 \begin{cquote} 2207 2266 \lstDeleteShortInline@% … … 2222 2281 \lstMakeShortInline@% 2223 2282 \end{cquote} 2224 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.2283 In additon, there are polymorphic functions, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@. 2225 2284 2226 2285 The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety. … … 2239 2298 An array may be filled, resized, or aligned. 2240 2299 \end{description} 2241 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. 2242 2243 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2244 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety: 2245 \begin{cquote} 2246 \begin{cfa}[aboveskip=0pt] 2247 size_t dim = 10; $\C{// array dimension}$ 2248 char fill = '\xff'; $\C{// initialization fill value}$ 2249 int * ip; 2250 \end{cfa} 2251 \lstDeleteShortInline@% 2252 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2253 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2254 \begin{cfa} 2255 ip = alloc(); 2256 ip = alloc( fill ); 2257 ip = alloc( dim ); 2258 ip = alloc( dim, fill ); 2259 ip = alloc( ip, 2 * dim ); 2260 ip = alloc( ip, 4 * dim, fill ); 2261 2262 ip = align_alloc( 16 ); 2263 ip = align_alloc( 16, fill ); 2264 ip = align_alloc( 16, dim ); 2265 ip = align_alloc( 16, dim, fill ); 2266 \end{cfa} 2267 & 2268 \begin{cfa} 2269 ip = (int *)malloc( sizeof( int ) ); 2270 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2271 ip = (int *)malloc( dim * sizeof( int ) ); 2272 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2273 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2274 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2275 2276 ip = memalign( 16, sizeof( int ) ); 2277 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2278 ip = memalign( 16, dim * sizeof( int ) ); 2279 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2280 \end{cfa} 2281 \end{tabular} 2282 \lstMakeShortInline@% 2283 \end{cquote} 2284 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2285 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg: 2286 \begin{cfa} 2287 struct S { int i, j; }; 2288 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2289 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2290 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2291 \end{cfa} 2292 Note, \CC can only initialization array elements via the default constructor. 2293 2294 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. 2295 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2300 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-functions and how all the capabilities can be combined into two \CFA functions. 2301 \CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size. 2302 Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety. 2296 2303 2297 2304 \begin{table} … … 2319 2326 \end{table} 2320 2327 2328 \begin{figure} 2329 \centering 2330 \begin{cquote} 2331 \begin{cfa}[aboveskip=0pt] 2332 size_t dim = 10; $\C{// array dimension}$ 2333 char fill = '\xff'; $\C{// initialization fill value}$ 2334 int * ip; 2335 \end{cfa} 2336 \lstDeleteShortInline@% 2337 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}} 2338 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{C}} \\ 2339 \begin{cfa} 2340 ip = alloc(); 2341 ip = alloc( fill ); 2342 ip = alloc( dim ); 2343 ip = alloc( dim, fill ); 2344 ip = alloc( ip, 2 * dim ); 2345 ip = alloc( ip, 4 * dim, fill ); 2346 2347 ip = align_alloc( 16 ); 2348 ip = align_alloc( 16, fill ); 2349 ip = align_alloc( 16, dim ); 2350 ip = align_alloc( 16, dim, fill ); 2351 \end{cfa} 2352 & 2353 \begin{cfa} 2354 ip = (int *)malloc( sizeof( int ) ); 2355 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2356 ip = (int *)malloc( dim * sizeof( int ) ); 2357 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2358 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) ); 2359 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) ); 2360 2361 ip = memalign( 16, sizeof( int ) ); 2362 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) ); 2363 ip = memalign( 16, dim * sizeof( int ) ); 2364 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) ); 2365 \end{cfa} 2366 \end{tabular} 2367 \lstMakeShortInline@% 2368 \end{cquote} 2369 \caption{\CFA versus C Storage-Allocation} 2370 \label{f:StorageAllocation} 2371 \end{figure} 2372 2373 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization. 2374 Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg: 2375 \begin{cfa} 2376 struct S { int i, j; }; 2377 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; } 2378 S * s = new( 2, 3 ); $\C{// allocate storage and run constructor}$ 2379 S * as = anew( dim, 2, 3 ); $\C{// each array element initialized to 2, 3}$ 2380 \end{cfa} 2381 Note, \CC can only initialization array elements via the default constructor. 2382 2383 Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap. 2384 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character. 2385 2321 2386 2322 2387 \subsection{I/O} … … 2406 2471 }% 2407 2472 \end{itemize} 2408 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.2473 There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output. 2409 2474 2410 2475 … … 2413 2478 2414 2479 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP. 2415 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.2480 The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers. 2416 2481 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@. 2417 2482 The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces. … … 2458 2523 Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks would show little runtime variance, other than in length and clarity of source code. 2459 2524 A more illustrative benchmark measures the costs of idiomatic usage of each language's features. 2460 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ routinesimilar to that in Section~\ref{sec:variadic-tuples}.2525 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ function similar to that in Section~\ref{sec:variadic-tuples}. 2461 2526 The benchmark test is similar for C and \CC. 2462 2527 The experiment uses element types @int@ and @pair(_Bool, char)@, and pushes $N=40M$ elements on a generic stack, copies the stack, clears one of the stacks, finds the maximum value in the other stack, and prints $N/2$ (to reduce graph height) constants. … … 2472 2537 TIMED( "copy_int", t = s; ) 2473 2538 TIMED( "clear_int", clear( s ); ) 2474 REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); )2539 REPEAT_TIMED( "pop_int", N, int v = pop( t ); max = max( v, max ); ) 2475 2540 REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; ) 2476 2541 … … 2481 2546 TIMED( "copy_pair", t = s; ) 2482 2547 TIMED( "clear_pair", clear( s ); ) 2483 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); )2548 REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) v = pop( t ); max = max( v, max ); ) 2484 2549 REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; ) 2485 2550 } … … 2553 2618 \CC is the most similar language to \CFA; 2554 2619 both are extensions to C with source and runtime backwards compatibility. 2555 The fundamental difference is in their engineering approach toC compatibility and programmer expectation.2556 While \CC provides good backwardscompatibility with C, it has a steep learning curve for many of its extensions.2620 The fundamental difference is the engineering approach to maintain C compatibility and programmer expectation. 2621 While \CC provides good compatibility with C, it has a steep learning curve for many of its extensions. 2557 2622 For example, polymorphism is provided via three disjoint mechanisms: overloading, inheritance, and templates. 2558 2623 The overloading is restricted because resolution does not use the return type, inheritance requires learning object-oriented programming and coping with a restricted nominal-inheritance hierarchy, templates cannot be separately compiled resulting in compilation/code bloat and poor error messages, and determining how these mechanisms interact and which to use is confusing. 2559 2624 In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate-compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm. 2560 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed properties for a type.2561 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function in codebeyond compilation errors during template expansion;2625 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties. 2626 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function beyond compilation errors during template expansion; 2562 2627 furthermore, \CC concepts are restricted to template polymorphism. 2563 2628 … … 2610 2675 2611 2676 2677 \subsection{Control Structures / Declarations / Literals} 2678 2679 2612 2680 \section{Conclusion and Future Work} 2613 2681 … … 2669 2737 stack_node(T) ** crnt = &s.head; 2670 2738 for ( stack_node(T) * next = t.head; next; next = next->next ) { 2671 *crnt = malloc(){ next->value }; 2739 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2740 (*new_node){ next->value }; /***/ 2741 *crnt = new_node; 2672 2742 stack_node(T) * acrnt = *crnt; 2673 2743 crnt = &acrnt->next; … … 2684 2754 forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; } 2685 2755 forall(otype T) void push( stack(T) & s, T value ) { 2686 s.head = malloc(){ value, s.head }; 2756 stack_node(T) * new_node = ((stack_node(T)*)malloc()); 2757 (*new_node){ value, s.head }; /***/ 2758 s.head = new_node; 2687 2759 } 2688 2760 forall(otype T) T pop( stack(T) & s ) { 2689 2761 stack_node(T) * n = s.head; 2690 2762 s.head = n->next; 2691 T x = n->value; 2692 ^n{}; 2693 free( n ); 2694 return x; 2763 T v = n->value; 2764 delete( n ); 2765 return v; 2695 2766 } 2696 2767 forall(otype T) void clear( stack(T) & s ) { … … 2848 2919 2849 2920 2850 \begin{comment}2851 \subsubsection{bench.h}2852 (\texttt{bench.hpp} is similar.)2853 2854 \lstinputlisting{evaluation/bench.h}2855 2856 \subsection{C}2857 2858 \subsubsection{c-stack.h} ~2859 2860 \lstinputlisting{evaluation/c-stack.h}2861 2862 \subsubsection{c-stack.c} ~2863 2864 \lstinputlisting{evaluation/c-stack.c}2865 2866 \subsubsection{c-pair.h} ~2867 2868 \lstinputlisting{evaluation/c-pair.h}2869 2870 \subsubsection{c-pair.c} ~2871 2872 \lstinputlisting{evaluation/c-pair.c}2873 2874 \subsubsection{c-print.h} ~2875 2876 \lstinputlisting{evaluation/c-print.h}2877 2878 \subsubsection{c-print.c} ~2879 2880 \lstinputlisting{evaluation/c-print.c}2881 2882 \subsubsection{c-bench.c} ~2883 2884 \lstinputlisting{evaluation/c-bench.c}2885 2886 \subsection{\CFA}2887 2888 \subsubsection{cfa-stack.h} ~2889 2890 \lstinputlisting{evaluation/cfa-stack.h}2891 2892 \subsubsection{cfa-stack.c} ~2893 2894 \lstinputlisting{evaluation/cfa-stack.c}2895 2896 \subsubsection{cfa-print.h} ~2897 2898 \lstinputlisting{evaluation/cfa-print.h}2899 2900 \subsubsection{cfa-print.c} ~2901 2902 \lstinputlisting{evaluation/cfa-print.c}2903 2904 \subsubsection{cfa-bench.c} ~2905 2906 \lstinputlisting{evaluation/cfa-bench.c}2907 2908 \subsection{\CC}2909 2910 \subsubsection{cpp-stack.hpp} ~2911 2912 \lstinputlisting[language=c++]{evaluation/cpp-stack.hpp}2913 2914 \subsubsection{cpp-print.hpp} ~2915 2916 \lstinputlisting[language=c++]{evaluation/cpp-print.hpp}2917 2918 \subsubsection{cpp-bench.cpp} ~2919 2920 \lstinputlisting[language=c++]{evaluation/cpp-bench.cpp}2921 2922 \subsection{\CCV}2923 2924 \subsubsection{object.hpp} ~2925 2926 \lstinputlisting[language=c++]{evaluation/object.hpp}2927 2928 \subsubsection{cpp-vstack.hpp} ~2929 2930 \lstinputlisting[language=c++]{evaluation/cpp-vstack.hpp}2931 2932 \subsubsection{cpp-vstack.cpp} ~2933 2934 \lstinputlisting[language=c++]{evaluation/cpp-vstack.cpp}2935 2936 \subsubsection{cpp-vprint.hpp} ~2937 2938 \lstinputlisting[language=c++]{evaluation/cpp-vprint.hpp}2939 2940 \subsubsection{cpp-vbench.cpp} ~2941 2942 \lstinputlisting[language=c++]{evaluation/cpp-vbench.cpp}2943 \end{comment}2944 2945 2921 \end{document} 2946 2922 -
src/tests/.expect/literals.x64.txt
r0a2168f rea46db7 522 522 signed int __main__Fi___1(){ 523 523 __attribute__ ((unused)) signed int ___retval_main__i_1; 524 ((void)0b01101011); 525 ((void)0b01101011u); 526 ((void)0b01101011l); 527 ((void)0b01101011ll); 528 ((void)0b01101011ul); 529 ((void)0b01101011lu); 530 ((void)0b01101011ull); 531 ((void)0b01101011llu); 532 ((void)(+0b01101011)); 533 ((void)(+0b01101011u)); 534 ((void)(+0b01101011l)); 535 ((void)(+0b01101011ll)); 536 ((void)(+0b01101011ul)); 537 ((void)(+0b01101011lu)); 538 ((void)(+0b01101011ull)); 539 ((void)(+0b01101011llu)); 540 ((void)(-0b01101011)); 541 ((void)(-0b01101011u)); 542 ((void)(-0b01101011l)); 543 ((void)(-0b01101011ll)); 544 ((void)(-0b01101011ul)); 545 ((void)(-0b01101011lu)); 546 ((void)(-0b01101011ull)); 547 ((void)(-0b01101011llu)); 524 548 ((void)01234567); 525 549 ((void)01234567u); … … 1017 1041 ((void)(-0X0123456789.0123456789P-09F)); 1018 1042 ((void)(-0X0123456789.0123456789P-09L)); 1043 ((void)((signed char )0b01101011)); 1044 ((void)((signed short int )0b01101011)); 1045 ((void)((signed int )0b01101011)); 1046 ((void)((signed long int )0b01101011)); 1047 ((void)((__int128 )0b01101011)); 1048 ((void)((unsigned char )0b01101011u)); 1049 ((void)((signed short int )0b01101011u)); 1050 ((void)((unsigned int )0b01101011u)); 1051 ((void)((signed long int )0b01101011u)); 1052 ((void)((__int128 )0b01101011u)); 1053 ((void)(+((signed int )((signed char )0b01101011)))); 1054 ((void)(+((signed int )((signed short int )0b01101011)))); 1055 ((void)(+((signed int )0b01101011))); 1056 ((void)(+((signed long int )0b01101011))); 1057 ((void)(+((float )((__int128 )0b01101011)))); 1058 ((void)(+((signed int )((unsigned char )0b01101011u)))); 1059 ((void)(+((signed int )((signed short int )0b01101011u)))); 1060 ((void)(+((unsigned int )0b01101011u))); 1061 ((void)(+((signed long int )0b01101011u))); 1062 ((void)(+((float )((__int128 )0b01101011u)))); 1063 ((void)(-((signed int )((signed char )0b01101011)))); 1064 ((void)(-((signed int )((signed short int )0b01101011)))); 1065 ((void)(-((signed int )0b01101011))); 1066 ((void)(-((signed long int )0b01101011))); 1067 ((void)(-((float )((__int128 )0b01101011)))); 1068 ((void)(-((signed int )((unsigned char )0b01101011u)))); 1069 ((void)(-((signed int )((signed short int )0b01101011u)))); 1070 ((void)(-((unsigned int )0b01101011u))); 1071 ((void)(-((signed long int )0b01101011u))); 1072 ((void)(-((float )((__int128 )0b01101011u)))); 1019 1073 ((void)((signed char )01234567)); 1020 1074 ((void)((signed short int )01234567)); -
src/tests/.expect/user_literals.txt
r0a2168f rea46db7 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/literals.c
r0a2168f rea46db7 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
r0a2168f rea46db7 10 10 // Created On : Wed Sep 6 21:40:50 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Dec 7 09:12:36 201713 // Update Count : 5 012 // Last Modified On : Sun Mar 4 11:14:02 2018 13 // Update Count : 52 14 14 // 15 15 … … 31 31 32 32 33 struct Weight { 34 double stones; 35 }; 36 void ?{}( Weight & w ) { w.stones = 0; } // operations 33 struct Weight { double stones; }; 34 void ?{}( Weight & w ) { w.stones = 0; } 37 35 void ?{}( Weight & w, double w ) { w.stones = w; } 38 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; } 36 Weight ?+?( Weight l, Weight r ) { 37 return (Weight){ l.stones + r.stones }; 38 } 39 39 ofstream & ?|?( ofstream & os, Weight w ) { return os | w.stones; } 40 40 41 41 Weight ?`st( double w ) { return (Weight){ w }; } // backquote for user literals 42 42 Weight ?`lb( double w ) { return (Weight){ w / 14.0 }; } 43 Weight ?`kg( double w ) { return (Weight) { w * 0.1575}; } 44 43 Weight ?`kg( double w ) { return (Weight) { w * 0.16 }; } 45 44 46 45 int main() { 47 Weight w, hw = { 14 }; // 14 stone 48 w = 11`st + 1`lb; 46 Weight w, heavy = { 20 }; // 20 stone 47 w = 155`lb; 48 sout | w | endl; 49 w = 0b_1111`st; 50 sout | w | endl; 51 w = 0_233`lb; // octal weight (155) 52 sout | w | endl; 53 w = 0x_9b_u`kg; 49 54 sout | w | endl; 50 55 w = 70.3`kg; 51 56 sout | w | endl; 52 w = 1 55`lb;57 w = 11`st + 1`lb; 53 58 sout | w | endl; 54 w = 0x_9b_u`lb; // hexadecimal unsigned weight (155) 55 sout | w | endl; 56 w = 0_233`lb; // octal weight (155) 57 sout | w | endl; 58 w = 5`st + 8`kg + 25`lb + hw; 59 w = 5`st + 8`kg + 25`lb + heavy; 59 60 sout | w | endl; 60 61
Note: See TracChangeset
for help on using the changeset viewer.