Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/general/Paper.tex

    r06b176d rc659968  
    22
    33\usepackage{fullpage}
    4 \usepackage{epic,eepic}
    54\usepackage{xspace,calc,comment}
    65\usepackage{upquote}                                                                    % switch curled `'" to straight
     
    3736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    3837
    39 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
     38\newcommand{\Textbf}[1]{{\color{red}\textbf{#1}}}
    4039\newcommand{\TODO}[1]{\textbf{TODO}: {\itshape #1}} % TODO included
    4140%\newcommand{\TODO}[1]{} % TODO elided
     
    10531052\label{s:WithClauseStatement}
    10541053
    1055 Grouping heterogenous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
     1054Grouping heterogenous data into \newterm{aggregate}s is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
    10561055\begin{cfa}
    1057 struct S {                                                                      $\C{// aggregate}$
    1058         char c;                                                                 $\C{// fields}$
     1056struct S {                                                              $\C{// aggregate}$
     1057        char c;                                                         $\C{// fields}$
    10591058        int i;
    10601059        double d;
     
    10621061S s, as[10];
    10631062\end{cfa}
    1064 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:
     1063However, routines manipulating aggregates have repeition of the aggregate name to access its containing fields:
    10651064\begin{cfa}
    10661065void f( S s ) {
    1067         `s.`c; `s.`i; `s.`d;                                    $\C{// access containing fields}$
     1066        `s.`c; `s.`i; `s.`d;                            $\C{// access containing fields}$
    10681067}
    10691068\end{cfa}
     
    10711070\begin{C++}
    10721071class C {
    1073         char c;                                                                 $\C{// fields}$
     1072        char c;                                                         $\C{// fields}$
    10741073        int i;
    10751074        double d;
    1076         int mem() {                                                             $\C{// implicit "this" parameter}$
    1077                 `this->`c; `this->`i; `this->`d;        $\C{// access containing fields}$
     1075        int mem() {                                                     $\C{// implicit "this" parameter}$
     1076                `this->`c; `this->`i; `this->`d;$\C{// access containing fields}$
    10781077        }
    10791078}
    10801079\end{C++}
    1081 Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
    1082 However, for other aggregate parameters, qualification is necessary:
    1083 \begin{cfa}
    1084 struct T { double m, n; };
    1085 int C::mem( T & t ) {                                           $\C{// multiple aggregate parameters}$
    1086         c; i; d;                                                                $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$
    1087         `t.`m; `t.`n;                                                   $\C{// must qualify}$
    1088 }
    1089 \end{cfa}
     1080Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of nested lexical-scoping.
    10901081
    10911082% In object-oriented programming, there is an implicit first parameter, often names @self@ or @this@, which is elided.
     
    10971088% \TODO{Fill out section. Be sure to mention arbitrary expressions in with-blocks, recent change driven by Thierry to prioritize field name over parameters.}
    10981089
    1099 To simplify the programmer experience, \CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers.
    1100 Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block.
     1090\CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing field identifiers.
     1091Hence, the qualified fields become variables, and making it easier to optimize field references in a block.
    11011092\begin{cfa}
    1102 void f( S s ) `with( s )` {                                     $\C{// with clause}$
    1103         c; i; d;                                                                $\C{\color{red}// s.c, s.i, s.d}$
     1093void f( S s ) `with( s )` {                             $\C{// with clause}$
     1094        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
    11041095}
    11051096\end{cfa}
     
    11071098\begin{cfa}
    11081099int mem( S & this ) `with( this )` {            $\C{// with clause}$
    1109         c; i; d;                                                                $\C{\color{red}// this.c, this.i, this.d}$
     1100        c; i; d;                                                        $\C{\color{red}// this.c, this.i, this.d}$
    11101101}
    11111102\end{cfa}
    1112 with the generality of opening multiple aggregate-parameters:
     1103The key generality over the object-oriented approach is that one aggregate parameter \lstinline[language=C++]@this@ is not treated specially over other aggregate parameters:
    11131104\begin{cfa}
     1105struct T { double m, n; };
    11141106int mem( S & s, T & t ) `with( s, t )` {        $\C{// multiple aggregate parameters}$
    1115         c; i; d;                                                                $\C{\color{red}// s.c, s.i, s.d}$
    1116         m; n;                                                                   $\C{\color{red}// t.m, t.n}$
     1107        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
     1108        m; n;                                                           $\C{\color{red}// t.m, t.n}$
    11171109}
    11181110\end{cfa}
    1119 
    1120 In detail, the @with@ clause/statement has the form:
     1111The equivalent object-oriented style is:
    11211112\begin{cfa}
    1122 $\emph{with-statement}$:
    1123         'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
    1124 \end{cfa}
    1125 and may appear as the body of a routine or nested within a routine body.
    1126 Each expression in the expression-list provides a type and object.
    1127 The type must be an aggregate type.
    1128 (Enumerations are already opened.)
    1129 The object is the implicit qualifier for the open structure-fields.
    1130 
    1131 All expressions in the expression list are open in ``parallel'' within the compound statement.
    1132 This semantic is different from Pascal, which nests the openings.
    1133 The difference between parallel and nesting occurs for fields with the same name but different type:
    1134 \begin{cfa}
    1135 struct S { int i; int j; double m; } s, w;
    1136 struct T { int i; int k; int m } t, w;
    1137 with( s, t ) {
    1138         j + k;                                                                  $\C{// unambiguous, s.j + t.m}$
    1139         m = 5.0;                                                                $\C{// unambiguous, t.m = 5.0}$
    1140         m = 1;                                                                  $\C{// unambiguous, s.m = 1}$
    1141         int a = s.i + m;                                                $\C{// unambiguous, a = s.i + t.i}$
    1142         int b = s.i + t.i;                                              $\C{// unambiguous, qualification}$
    1143         sout | (double)m | endl;                                $\C{// unambiguous, cast}$
    1144         i;                                                                              $\C{// ambiguous}$
    1145 }
    1146 \end{cfa}
    1147 \CFA's ability to overload variables means usages of field with the same names can be automatically disambiguated, eliminating most qualification.
    1148 Qualification or a cast is used to disambiguate.
    1149 A cast may be necessary to disambiguate between the overload variables in a @with@ expression:
    1150 \begin{cfa}
    1151 with( w ) { ... }                                                       $\C{// ambiguous, same name and no context}$
    1152 with( (S)w ) { ... }                                            $\C{// unambiguous}$
    1153 \end{cfa}
    1154 
    1155 \begin{cfa}
    1156 struct S { int i, j; } sv;
    1157 with( sv ) {
    1158         S & sr = sv;
    1159         with( sr ) {
    1160                 S * sp = &sv;
    1161                 with( *sp ) {
    1162                         i = 3; j = 4;                                   $\C{\color{red}// sp-{\textgreater}i, sp-{\textgreater}j}$
    1163                 }
    1164                 i = 3; j = 4;                                           $\C{\color{red}// sr.i, sr.j}$
    1165         }
    1166         i = 3; j = 4;                                                   $\C{\color{red}// sv.i, sv.j}$
     1113int S::mem( T & t ) {                                   $\C{// multiple aggregate parameters}$
     1114        c; i; d;                                                        $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$
     1115        `t.`m; `t.`n;
    11671116}
    11681117\end{cfa}
     
    11731122        struct S1 { ... } s1;
    11741123        struct S2 { ... } s2;
    1175         `with( s1 )` {                                                  $\C{// with statement}$
     1124        `with( s1 )` {                                          $\C{// with statement}$
    11761125                // access fields of s1 without qualification
    1177                 `with( s2 )` {                                          $\C{// nesting}$
     1126                `with( s2 )` {                                  $\C{// nesting}$
    11781127                        // access fields of s1 and s2 without qualification
    11791128                }
     
    11851134\end{cfa}
    11861135
     1136When opening multiple structures, fields with the same name and type are ambiguous and must be fully qualified.
     1137For fields with the same name but different type, context/cast can be used to disambiguate.
     1138\begin{cfa}
     1139struct S { int i; int j; double m; } a, c;
     1140struct T { int i; int k; int m } b, c;
     1141`with( a, b )` {
     1142        j + k;                                                  $\C{// unambiguous, unique names define unique types}$
     1143        i;                                                              $\C{// ambiguous, same name and type}$
     1144        a.i + b.i;                                              $\C{// unambiguous, qualification defines unique names}$
     1145        m;                                                              $\C{// ambiguous, same name and no context to define unique type}$
     1146        m = 5.0;                                                $\C{// unambiguous, same name and context defines unique type}$
     1147        m = 1;                                                  $\C{// unambiguous, same name and context defines unique type}$
     1148}
     1149`with( c )` { ... }                                     $\C{// ambiguous, same name and no context}$
     1150`with( (S)c )` { ... }                                  $\C{// unambiguous, same name and cast defines unique type}$
     1151\end{cfa}
     1152
     1153The components in the "with" clause
     1154
     1155  with ( a, b, c ) { ... }
     1156
     1157serve 2 purposes: each component provides a type and object. The type must be a
     1158structure type. Enumerations are already opened, and I think a union is opened
     1159to some extent, too. (Or is that just unnamed unions?) The object is the target
     1160that the naked structure-fields apply to. The components are open in "parallel"
     1161at the scope of the "with" clause/statement, so opening "a" does not affect
     1162opening "b", etc. This semantic is different from Pascal, which nests the
     1163openings.
     1164
     1165Having said the above, it seems reasonable to allow a "with" component to be an
     1166expression. The type is the static expression-type and the object is the result
     1167of the expression. Again, the type must be an aggregate. Expressions require
     1168parenthesis around the components.
     1169
     1170  with( a, b, c ) { ... }
     1171
     1172Does this now make sense?
     1173
     1174Having written more CFA code, it is becoming clear to me that I *really* want
     1175the "with" to be implemented because I hate having to type all those object
     1176names for fields. It's a great way to drive people away from the language.
     1177
    11871178
    11881179\subsection{Exception Handling ???}
     
    11981189
    11991190\subsection{Alternative Declaration Syntax}
    1200 
    1201 \newcommand{\R}[1]{\Textbf{#1}}
    1202 \newcommand{\B}[1]{{\Textbf[blue]{#1}}}
    1203 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    1204 
    1205 C declaration syntax is notoriously confusing and error prone.
    1206 For example, many C programmers are confused by a declaration as simple as:
    1207 \begin{flushleft}
    1208 \lstDeleteShortInline@%
    1209 \begin{tabular}{@{}ll@{}}
    1210 \begin{cfa}
    1211 int * x[5]
    1212 \end{cfa}
    1213 &
    1214 \raisebox{-0.75\totalheight}{\input{Cdecl}}
    1215 \end{tabular}
    1216 \lstMakeShortInline@%
    1217 \end{flushleft}
    1218 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers?
    1219 The fact this declaration is unclear to many C programmers means there are productivity and safety issues even for basic programs.
    1220 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.
    1221 For example, a routine returning a pointer to an array of integers is defined and used in the following way:
    1222 \begin{cfa}
    1223 int `(*`f`())[`5`]` {...};                              $\C{// definition}$
    1224  ... `(*`f`())[`3`]` += 1;                              $\C{// usage}$
    1225 \end{cfa}
    1226 Essentially, the return type is wrapped around the routine name in successive layers (like an onion).
    1227 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    1228 
    1229 \CFA provides its own type, variable and routine declarations, using a different syntax.
    1230 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type.
    1231 In the following example, \R{red} is the base type and \B{blue} is qualifiers.
    1232 The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    1233 \begin{quote}
    1234 \lstDeleteShortInline@%
    1235 \lstset{moredelim=**[is][\color{blue}]{+}{+}}
    1236 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1237 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1238 \begin{cfa}
    1239 +[5] *+ `int` x1;
    1240 +* [5]+ `int` x2;
    1241 +[* [5] int]+ f`( int p )`;
    1242 \end{cfa}
    1243 &
    1244 \begin{cfa}
    1245 `int` +*+ x1 +[5]+;
    1246 `int` +(*+x2+)[5]+;
    1247 +int (*+f`( int p )`+)[5]+;
    1248 \end{cfa}
    1249 \end{tabular}
    1250 \lstMakeShortInline@%
    1251 \end{quote}
    1252 The only exception is bit field specification, which always appear to the right of the base type.
    1253 % Specifically, the character ©*© is used to indicate a pointer, square brackets ©[©\,©]© are used to represent an array or function return value, and parentheses ©()© are used to indicate a routine parameter.
    1254 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    1255 For instance, variables ©x© and ©y© of type pointer to integer are defined in \CFA as follows:
    1256 \begin{quote}
    1257 \lstDeleteShortInline@%
    1258 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1259 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1260 \begin{cfa}
    1261 `*` int x, y;
    1262 \end{cfa}
    1263 &
    1264 \begin{cfa}
    1265 int `*`x, `*`y;
    1266 \end{cfa}
    1267 \end{tabular}
    1268 \lstMakeShortInline@%
    1269 \end{quote}
    1270 The downside of this semantics is the need to separate regular and pointer declarations:
    1271 \begin{quote}
    1272 \lstDeleteShortInline@%
    1273 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1274 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1275 \begin{cfa}
    1276 `*` int x;
    1277 int y;
    1278 \end{cfa}
    1279 &
    1280 \begin{cfa}
    1281 int `*`x, y;
    1282 
    1283 \end{cfa}
    1284 \end{tabular}
    1285 \lstMakeShortInline@%
    1286 \end{quote}
    1287 which is prescribing a safety benefit.
    1288 Other examples are:
    1289 \begin{quote}
    1290 \lstDeleteShortInline@%
    1291 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1292 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1293 \begin{cfa}
    1294 [ 5 ] int z;
    1295 [ 5 ] * char w;
    1296 * [ 5 ] double v;
    1297 struct s {
    1298         int f0:3;
    1299         * int f1;
    1300         [ 5 ] * int f2;
    1301 };
    1302 \end{cfa}
    1303 &
    1304 \begin{cfa}
    1305 int z[ 5 ];
    1306 char * w[ 5 ];
    1307 double (* v)[ 5 ];
    1308 struct s {
    1309         int f0:3;
    1310         int * f1;
    1311         int * f2[ 5 ]
    1312 };
    1313 \end{cfa}
    1314 &
    1315 \begin{cfa}
    1316 // array of 5 integers
    1317 // array of 5 pointers to char
    1318 // pointer to array of 5 doubles
    1319 
    1320 // common bit field syntax
    1321 
    1322 
    1323 
    1324 \end{cfa}
    1325 \end{tabular}
    1326 \lstMakeShortInline@%
    1327 \end{quote}
    1328 
    1329 All type qualifiers, \eg ©const©, ©volatile©, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
    1330 \begin{quote}
    1331 \lstDeleteShortInline@%
    1332 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    1333 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
    1334 \begin{cfa}
    1335 const * const int x;
    1336 const * [ 5 ] const int y;
    1337 \end{cfa}
    1338 &
    1339 \begin{cfa}
    1340 int const * const x;
    1341 const int (* const y)[ 5 ]
    1342 \end{cfa}
    1343 &
    1344 \begin{cfa}
    1345 // const pointer to const integer
    1346 // const pointer to array of 5 const integers
    1347 \end{cfa}
    1348 \end{tabular}
    1349 \lstMakeShortInline@%
    1350 \end{quote}
    1351 All declaration qualifiers, \eg ©extern©, ©static©, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier}
    1352 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg:
    1353 \begin{quote}
    1354 \lstDeleteShortInline@%
    1355 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1356 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1357 \begin{cfa}
    1358 extern [ 5 ] int x;
    1359 static * const int y;
    1360 \end{cfa}
    1361 &
    1362 \begin{cfa}
    1363 int extern x[ 5 ];
    1364 const int static * y;
    1365 \end{cfa}
    1366 &
    1367 \begin{cfa}
    1368 // externally visible array of 5 integers
    1369 // internally visible pointer to constant int
    1370 \end{cfa}
    1371 \end{tabular}
    1372 \lstMakeShortInline@%
    1373 \end{quote}
    1374 
    1375 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine ©sizeof©:
    1376 \begin{quote}
    1377 \lstDeleteShortInline@%
    1378 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1379 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1380 \begin{cfa}
    1381 y = (`* int`)x;
    1382 i = sizeof(`[ 5 ] * int`);
    1383 \end{cfa}
    1384 &
    1385 \begin{cfa}
    1386 y = (`int *`)x;
    1387 i = sizeof(`int * [ 5 ]`);
    1388 \end{cfa}
    1389 \end{tabular}
    1390 \lstMakeShortInline@%
    1391 \end{quote}
    1392 
    1393 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    1394 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1395 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX systems.
    13961191
    13971192
     
    14441239In \CFA, the address of a @T&@ is a lvalue @T*@, as the address of the underlying @T@ is stored in the reference, and can thus be mutated there.
    14451240The result of this rule is that any reference can be rebound using the existing pointer assignment semantics by assigning a compatible pointer into the address of the reference, \eg @&r1 = &x;@ above.
    1446 This rebinding can occur to an arbitrary depth of reference nesting; $n$ address-of operators applied to a reference nested $m$ times will produce an lvalue pointer nested $n$ times if $n \le m$ (note that $n = m+1$ is simply the usual C rvalue address-of operator applied to the $n = m$ case).
    1447 The explicit address-of operators can be thought of as ``cancelling out'' the implicit dereference operators, \eg @(&`*`)r1 = &x@ or @(&(&`*`)`*`)r3 = &(&`*`)r1@ or even @(&`*`)r2 = (&`*`)`*`r3@ for @&r2 = &r3@.
     1241This rebinding can occur to an arbitrary depth of reference nesting; loosely speaking, nested address-of operators will produce an lvalue nested pointer up to as deep as the reference they're applied to.
     1242These explicit address-of operators can be thought of as ``cancelling out'' the implicit dereference operators, \eg @(&`*`)r1 = &x@ or @(&(&`*`)`*`)r3 = &(&`*`)r1@ or even @(&`*`)r2 = (&`*`)`*`r3@ for @&r2 = &r3@.
     1243More precisely:
     1244\begin{itemize}
     1245        \item
     1246        if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) than @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
     1247       
     1248        \item
     1249        if @L@ is an lvalue of type {@T &@$_1 \cdots$@ &@$_l$} where $l \ge 0$ references (@&@ symbols) then @&L@ has type {@T `*`&@$_{\color{red}1} \cdots$@ &@$_{\color{red}l}$}, \\ \ie @T@ pointer with $l$ references (@&@ symbols).
     1250\end{itemize}
    14481251
    14491252Since pointers and references share the same internal representation, code using either is equally performant; in fact the \CFA compiler converts references to pointers internally, and the choice between them in user code can be made based solely on convenience.
     
    14801283In particular, \CFA does not implement class-based encapsulation: neither the constructor nor any other function has privileged access to the implementation details of a type, except through the translation-unit-scope method of opaque structs provided by C.
    14811284
    1482 In \CFA, a constructor is a function named @?{}@, while a destructor is a function named @^?{}@; like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @S s = { ... };@ or @^(s){};@.
     1285In \CFA, a constructor is a function named @?{}@, while a destructor is a function named @^?{}@; like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @x{ ... };@ or @^x{};@.
    14831286Every constructor and destructor must have a return type of @void@, and its first parameter must have a reference type whose base type is the type of the object the function constructs or destructs.
    14841287This first parameter is informally called the @this@ parameter, as in many object-oriented languages, though a programmer may give it an arbitrary name.
     
    15331336\begin{cfa}
    15341337Array a, b;
    1535 (a){};                                  $\C{// default construct}$
    1536 (b){ a };                               $\C{// copy construct}$
    1537 ^(a){};                                 $\C{// destruct}$
    1538 (a){ 5, 0xFFFFFFFF };   $\C{// explicit constructor call}$
     1338a{};                            $\C{// default construct}$
     1339b{ a };                         $\C{// copy construct}$
     1340^a{};                           $\C{// destruct}$
     1341a{ 5, 0xFFFFFFFF };     $\C{// explicit constructor call}$
    15391342\end{cfa}
    15401343
Note: See TracChangeset for help on using the changeset viewer.