- Timestamp:
- Jan 29, 2025, 9:07:21 AM (2 months ago)
- Branches:
- master
- Children:
- 49510db
- Parents:
- de8a0a4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified doc/theses/fangren_yu_MMath/content1.tex ¶
rde8a0a4 ra950021 2 2 \label{c:content1} 3 3 4 This chapter discusses \CFA feature introduced over time by multiple people and their interactions with the type system.4 This chapter discusses \CFA features introduced over time by multiple people and their interactions with the type system. 5 5 6 6 … … 19 19 Java has mutable references but no pointers. 20 20 \CC has mutable pointers but immutable references; 21 he nce, references match with functional programming.22 However, the consequence is asymmetr y semantics between thepointer and reference.21 here, references match with functional programming. 22 However, the consequence is asymmetric semantics between pointer and reference. 23 23 \CFA adopts a uniform policy between pointers and references where mutability is a separate property made at the declaration. 24 24 … … 64 64 The call applies an implicit dereference once to @x@ so the call is typed @f( int & )@ with @T = int@, rather than with @T = int &@. 65 65 66 As for a pointer type, a reference type may have qualifiers, where @const@ is most interesting.66 As for a pointer type, a reference type may have qualifiers, where @const@ is most common. 67 67 \begin{cfa} 68 68 int x = 3; $\C{// mutable}$ … … 113 113 In the initial \CFA reference design, the goal was to make the reference type a \emph{real} data type \vs a restricted \CC reference, which is mostly used for choosing the argument-passing method, \ie by-value or by-reference. 114 114 However, there is an inherent ambiguity for auto-dereferencing: every argument expression involving a reference variable can potentially mean passing the reference's value or address. 115 For example, in 116 \begin{cfa} 117 int & x; 118 forall( T ) void foo( T ); 119 forall( T ) void bar( T & ); 120 foo( x ); $\C{// means pass by value}$ 121 bar( x ); $\C{// means pass by reference}$ 122 \end{cfa} 123 the call to @foo@ must pass @x@ by value, implying auto-dereference, while the call to @bar@ must pass @x@ by reference, implying no auto-dereference. 115 124 Without any restrictions, this ambiguity limits the behaviour of reference types in \CFA polymorphic functions, where a type @T@ can bind to a reference or non-reference type. 116 125 This ambiguity prevents the type system treating reference types the same way as other types, even if type variables could be bound to reference types. … … 150 159 Even if the object trait can be made optional, the current type system often misbehaves by adding undesirable auto-dereference on the referenced-to value rather than the reference variable itself, as intended. 151 160 Some tweaks are necessary to accommodate reference types in polymorphic contexts and it is unclear what can or cannot be achieved. 152 Currently, there are contexts where \CFA programmer is forced to use a pointer type, giving up the benefits of auto-dereference operations and better syntax with reference types.161 Currently, there are contexts where the \CFA programmer is forced to use a pointer type, giving up the benefits of auto-dereference operations and better syntax with reference types. 153 162 154 163 … … 162 171 \begin{tabular}{@{}l@{\hspace{20pt}}l@{}} 163 172 \begin{cfa} 164 165 int foo( int &p2, int &p3 ); // in/out parameters 173 int foo( int &p1, int &p2 ); // in/out parameters 166 174 int x, y = 3, z = 4; 167 x = foo( y, z ); // return 3 values 175 x = foo( y, z ); // return 3 values: 1 out, 2 in/out 168 176 \end{cfa} 169 177 & 170 178 \begin{cfa} 171 struct Ret { int x, y, z; }; 172 Ret foo( int p2, int p3 ); // multiple return values 173 Ret ret = { .y = 3, .z = 4 }; 174 ret = foo( ret.y, ret.z ); // return 3 values 179 struct Ret { int x, y, z; } ret; 180 Ret foo( int p1, int p2 ); // return structure 181 ret = foo( 3, 4 ); // return 3 values: 3 out 175 182 \end{cfa} 176 183 \end{tabular} 177 184 \end{cquote} 178 K-W C allows direct return of multiple values into a tuple.179 \begin{cfa} 180 @[int, int, int]@ foo( int p 2, int p3);181 @[x, y, z]@ = foo( y, z); // return 3 values into a tuple185 Like Go, K-W C allows direct return of multiple values into a tuple. 186 \begin{cfa} 187 @[int, int, int]@ foo( int p1, int p2 ); 188 @[x, y, z]@ = foo( 3, 4 ); // return 3 values into a tuple 182 189 \end{cfa} 183 190 Along with making returning multiple values a first-class feature, tuples were extended to simplify a number of other common context that normally require multiple statements and/or additional declarations, all of which reduces coding time and errors. … … 205 212 bar( @foo@( 3 ), @foo@( 3 ) ); 206 213 \end{cfa} 207 The type resolver only has the tuple return types to resolve the call to @bar@ as the @foo@ parameters are identical, which involves unifying the flattened @foo@ return values with @bar@'s parameter list. 214 The type resolver only has the tuple return types to resolve the call to @bar@ as the @foo@ parameters are identical. 215 The resultion involves unifying the flattened @foo@ return values with @bar@'s parameter list. 208 216 However, no combination of @foo@s is an exact match with @bar@'s parameters; 209 217 thus, the resolver applies C conversions to obtain a best match. 210 218 The resulting minimal cost expression is @bar( foo@$_1$@( 3 ), foo@$_2$@( 3 ) )@, where the two possible coversions are (@int@, {\color{red}@int@}, @double@) to (@int@, {\color{red}@double@}, @double@) with a safe (widening) conversion from @int@ to @double@ versus ({\color{red}@double@}, {\color{red}@int@}, {\color{red}@int@}) to ({\color{red}@int@}, {\color{red}@double@}, {\color{red}@double@}) with one unsafe (narrowing) conversion from @double@ to @int@ and two safe conversions from @int@ to @double@. 211 The programming language Go provides a similar but simplier tuple mechanism, as it does not have overloaded functions. 219 Go provides a simplified mechanism where only one tuple returning function call is allowed and there are no implicit type conversions. 220 \begin{lstlisting}[language=Go] 221 func foo( int ) ( int, int, int ) { return 3, 7, 8 } 222 func bar( int, int, int ) { ... } // types must match 223 bar( foo( 3 ) ) // only one tuple returning call 224 \end{lstlisting} 225 Hence, programers cannot take advantage of the full power of tuples but type match is straightforward. 212 226 213 227 K-W C also supported tuple variables, but with a strong distinction between tuples and tuple values/variables. … … 305 319 \end{cfa} 306 320 \VRef[Figure]{f:AlternateTupleImplementation} shows the two implementation approaches. 307 In the left approach, the return statement is rewritten to pack the return values into a structure, which is returned by value, and the structure fields are indivi ually assigned to the left-hand side of the assignment.321 In the left approach, the return statement is rewritten to pack the return values into a structure, which is returned by value, and the structure fields are individually assigned to the left-hand side of the assignment. 308 322 In the right approach, the return statement is rewritten as direct assignments into the passed-in argument addresses. 309 The right imlementation looks more concise and saves unnecessarycopying.323 The upside of the right implementation is consistence and no copying. 310 324 The downside is indirection within @gives_two@ to access values, unless values get hoisted into registers for some period of time, which is common. 311 325 … … 314 328 \setlength{\tabcolsep}{20pt} 315 329 \begin{tabular}{@{}ll@{}} 316 Till K-W C implementation & Rodolfo\CFA implementation \\330 Till K-W C implementation & Esteves \CFA implementation \\ 317 331 \begin{cfa} 318 332 struct _tuple2 { int _0; int _1; } … … 343 357 344 358 Interestingly, in the third implementation of \CFA tuples by Robert Schluntz~\cite[\S~3]{Schluntz17}, the MVR functions revert back to structure based, where it remains in the current version of \CFA. 345 The reason for the reversion was to have a uniform approach for tuple values/variables making tuples first-class types in \CFA, \ie allow tuples with corresponding tuple variables. 346 This extension was possible, because in parallel with Schluntz's work, generic types were added independently by Moss~\cite{Moss19}, and the tuple variables leveraged the same implementation techniques as the generic variables. 347 \PAB{I'm not sure about the connection here. Do you have an example of what you mean?} 359 The reason for the reversion is a uniform approach for tuple values/variables making tuples first-class types in \CFA, \ie allow tuples with corresponding tuple variables. 360 This reversion was possible, because in parallel with Schluntz's work, generic types were added independently by Moss~\cite{Moss19}, and the tuple variables leveraged the same implementation techniques as for generic variables~\cite[\S~3.7]{Schluntz17}. 361 For example, these two tuples: 362 \begin{cfa} 363 [double, double] x; 364 [int, double, int] y; 365 \end{cfa} 366 are transformed internally into two generic structures: 367 \begin{cfa} 368 forall( T0 &, & T1 | sized( T0 ) | sized( T1 ) ) 369 struct _tuple2_ { 370 T0 field_0 ; T1 field_1 ; 371 }; 372 forall( T0 &, T1 &, T2 & | sized( T0 ) | sized( T1 ) | sized( T2 ) ) 373 struct _tuple3_ { 374 T0 field_0 ; T1 field_1 ; T2 field_2 ; 375 }; 376 \end{cfa} 377 and the declarations become instances of these generic structure types: 378 \begin{cfa} 379 _tuple2_( double, double ) x; 380 _tuple3_( int, double, int ) y; 381 \end{cfa} 382 Now types @_tuple2_@ and @_tuple3_@ are available for any further 2 or 3 tuple-types in the translation unit, simplifying internal code transformations by memoizing a small set of tuple structures. 383 Ultimately, these generic types are lowered to specific C structures during code generation. 384 Scala, like \CC, provides tuple types through a library using this structural expansion, \eg Scala provides tuple sizes 1 through 22 via hand-coded generic data-structures. 348 385 349 386 However, after experience gained building the \CFA runtime system, making tuple-types first-class seems to add little benefit. … … 361 398 Furthermore, since operator overloading in \CFA is implemented by treating operators as overloadable functions, tuple types are very rarely used in a structured way. 362 399 When a tuple-type expression appears in a function call (except assignment expressions, which are handled differently by mass- or multiple-assignment expansions), it is always flattened, and the tuple structure of function parameter is not considered a part of the function signatures. 363 For example, 400 For example, these two prototypes for @foo@: 364 401 \begin{cfa} 365 402 void f( int, int ); … … 367 404 f( 3, 4 ); // ambiguous call 368 405 \end{cfa} 369 the two prototypes for @foo@have the same signature (a function taking two @int@s and returning nothing), and therefore invalid overloads.406 have the same signature (a function taking two @int@s and returning nothing), and therefore invalid overloads. 370 407 Note, the ambiguity error occurs at the call rather than at the second declaration of @f@, because it is possible to have multiple equivalent prototype definitions of a function. 371 408 Furthermore, ordinary polymorphic type-parameters are not allowed to have tuple types. … … 385 422 Therefore, tuple types are never present in any fixed-argument function calls, because of the flattening. 386 423 424 \begin{comment} 425 Date: Mon, 13 Jan 2025 10:09:06 -0500 426 Subject: Re: structure / tuple 427 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca> 428 CC: Andrew Beach <ajbeach@uwaterloo.ca>, 429 Michael Brooks <mlbrooks@uwaterloo.ca>, 430 Fangren Yu <f37yu@uwaterloo.ca>, Jiada Liang <j82liang@uwaterloo.ca>, 431 Alvin Zhang <alvin.zhang@uwaterloo.ca>, 432 Kyoung Seo <lseo@plg.uwaterloo.ca> 433 From: Gregor Richards <gregor.richards@uwaterloo.ca> 434 435 Languages support tuples to abbreviate syntax where the meaning of several 436 values is obvious from context, such as returns from functions, or where the 437 effort of creating a dedicated type is not worth the reward of using that type 438 in exactly one location. The positions always have meanings which could be 439 given names, and are only not given names for brevity. Whether that brevity is 440 a good idea or not is the programmer's problem to deal with. I don't think 441 there's any pragmatic value to tuples beyond brevity. (From a theoretical 442 perspective, having the empty tuple is useful for type-theoretical reasons, and 443 tuples are usually easier to reason about than structures, but that only 444 applies to theoretical reasoning, not to actual programming.) 445 446 Your distinction unstructured tuples could just as well be made for structs as 447 well, if you had named arguments (or named returns?). Personally, I think that 448 having these be a syntactic distinction is a mistake. Other languages return 449 fully codified tuples, and if you immediately destructure them, even the most 450 naive optimizer will manage to never create an actual tuple in memory. In my 451 opinion, since tuples are for brevity, they should always be declared with your 452 "unstructured" syntax, and it's up to the optimizer to realize when you've 453 never stored them. But, you live closer to the metal in CFA than most 454 languages, so perhaps communicating that intent is of sufficient value. 455 456 The only value of tuples beyond that is to make it possible for annoying 457 students to use std::pair in place of ever creating their own class hierarchy 458 or naming things. Then again, I hear that that is one of the hard problems in 459 computer science. 460 461 With valediction, 462 - Gregor Richards 463 464 On 1/13/25 09:11, Peter A. Buhr wrote: 465 > The CFA team has been discussing the difference between a structure and 466 > tuple. Basically, a structure has named fields and a tuple has anonymous 467 > fields. As a result, structure access uses field names and tuple access uses 468 > position. 469 > 470 > struct S { int i, j, k ; }; 471 > S s; 472 > s.i; s.j; // field access 473 > 474 > tuple T { int, int }; 475 > T t; 476 > t.0; t.1; // position access, zero origin 477 > t[0]; t[1]; // alternate access 478 > 479 > Hence the difference is small. 480 > 481 > In CFA, we differentiate between unstructured and structured tuples. An 482 > unstructured tuple is a lexical grouping of potentially disjoint variables. 483 > 484 > [ int, int, int ] f(); 485 > void g( int, int, int ); 486 > x, y, z = f(); // Go unstructured tuple, flatten tuple 487 > g( foo() ); // flatten tuple 488 > 489 > Here, the tuple returned from f is flattened into disjoint variables. A 490 > structured tuple is like above and has contiguous memory. 491 > 492 > CFA has fancy unstructured stuff like 493 > 494 > s.[i,k] += 1; // add 1 to each field 495 > t.[1,0] = 1; // don't think this works but could 496 > 497 > which is just an unstructured tuple access (sugar). 498 > 499 > What is your opinion of structures and tuples since the difference is 500 > small. Why do many languages support both features? Are we missing some 501 > important aspect of tuples that differentiates them from structures? Is CFA 502 > unique in having both unstructured and structured tuples? 503 \end{comment} 504 387 505 Finally, a type-safe variadic argument signature was added by Robert Schluntz~\cite[\S~4.1.2]{Schluntz17} using @forall@ and a new tuple parameter-type, denoted by the keyword @ttype@ in Schluntz's implementation, but changed to the ellipsis syntax similar to \CC's template parameter pack. 388 506 For C variadics, \eg @va_list@, the number and types of the arguments must be conveyed in some way, \eg @printf@ uses a format string indicating the number and types of the arguments. 507 \begin{cfa} 508 int printf( const char * format, ${\color{red}\LARGE ...}$ ); // variadic list of variables to print 509 \end{cfa} 389 510 \VRef[Figure]{f:CVariadicMaxFunction} shows an $N$ argument @maxd@ function using the C untyped @va_list@ interface. 390 511 In the example, the first argument is the number of following arguments, and the following arguments are assumed to be @double@; … … 396 517 \begin{cfa} 397 518 double maxd( int @count@, @...@ ) { // ellipse parameter 398 399 400 401 402 403 404 405 406 519 double max = 0; 520 va_list args; 521 va_start( args, count ); 522 for ( int i = 0; i < count; i += 1 ) { 523 double num = va_arg( args, double ); 524 if ( num > max ) max = num; 525 } 526 va_end(args); 527 return max; 407 528 } 408 529 printf( "%g\n", maxd( @4@, 25.0, 27.3, 26.9, 25.7 ) ); … … 412 533 \end{figure} 413 534 414 There are two common patterns for using thevariadic functions in \CFA.535 There are two common patterns for using variadic functions in \CFA. 415 536 \begin{enumerate}[leftmargin=*] 416 537 \item … … 430 551 Structural recursion for processing the argument-pack values one at a time, \eg: 431 552 \begin{cfa} 432 forall( T | { int ? >?( T, T ); } )433 T max( T v1, T v2 ) { return v1 > v2 ? v1 : v2; }553 forall( T | { int ?<?( T, T ); } ) 554 T max( T v1, T v2 ) { return v1 < v2 ? v2 : v1; } 434 555 $\vspace{-10pt}$ 435 556 forall( T, TT ... | { T max( T, T ); T max( TT ); } ) 436 557 T max( T arg, TT args ) { return max( arg, max( args ) ); } 437 558 \end{cfa} 438 The first non-recursive @max@ function is the polymorphic base-case for the recursion, \ie, find the maximum of two identically typed values with a greater-than (@>@) operator.439 The second recursive @max@ function takes two parameters, a @T@ and a@TT@ tuple pack, handling all argument lengths greater than two.559 The first non-recursive @max@ function is the polymorphic base-case for the recursion, \ie, find the maximum of two identically typed values with a less-than (@<@) operator. 560 The second recursive @max@ function takes two parameters, @T@ and the @TT@ tuple pack, handling all argument lengths greater than two. 440 561 The recursive function computes the maximum for the first argument and the maximum value of the rest of the tuple pack. 441 562 The call of @max@ with one argument is the recursive call, where the tuple pack is converted into two arguments by taking the first value (lisp @car@) from the tuple pack as the first argument (flattening) and the remaining pack becomes the second argument (lisp @cdr@). … … 452 573 And because \CFA compiles polymorphic functions versus template expansion, many wrapper functions are generated to implement both user-defined generic-types and polymorphism with variadics. 453 574 Fortunately, the only permitted operations on polymorphic function parameters are given by the list of assertion (trait) functions. 454 Nevertheless, this small set of functions eventually need to be called with flattened tuple arguments.575 Nevertheless, this small set of functions eventually needs to be called with flattened tuple arguments. 455 576 Unfortunately, packing the variadic arguments into a rigid @struct@ type and generating all the required wrapper functions is significant work and largely wasted because most are never called. 456 577 Interested readers can refer to pages 77-80 of Robert Schluntz's thesis to see how verbose the translator output is to implement a simple variadic call with 3 arguments. 457 578 As the number of arguments increases, \eg a call with 5 arguments, the translator generates a concrete @struct@ types for a 4-tuple and a 3-tuple along with all the polymorphic type data for them. 458 579 An alternative approach is to put the variadic arguments into an array, along with an offset array to retrieve each individual argument. 459 This method is similar to how the C @va_list@ object is used (and how \CFA accesses polymorphic fields in a generic type), but the \CFA variadics generate the required type information to guarantee type safety .460 For example, given the following heterogeneous, variadic, typed @print@ and usage .580 This method is similar to how the C @va_list@ object is used (and how \CFA accesses polymorphic fields in a generic type), but the \CFA variadics generate the required type information to guarantee type safety (like the @printf@ format string). 581 For example, given the following heterogeneous, variadic, typed @print@ and usage: 461 582 \begin{cquote} 462 583 \begin{tabular}{@{}ll@{}} … … 487 608 } 488 609 \end{cfa} 489 where the fixed-arg polymorphism for @T@ can be handled by the standard @void *@-based \CFA polymorphic calling conventions, and the type information can allbe deduced at the call site.610 where the fixed-arg polymorphism for @T@ can be handled by the standard @void *@-based \CFA polymorphic calling conventions, and the type information can be deduced at the call site. 490 611 Note, the variadic @print@ supports heterogeneous types because the polymorphic @T@ is not returned (unlike variadic @max@), so there is no cascade of type relationships. 491 612 492 613 Turning tuples into first-class values in \CFA does have a few benefits, namely allowing pointers to tuples and arrays of tuples to exist. 493 However, it seems unlikely that these types have realistic use cases that cannot be achieved with out them.614 However, it seems unlikely that these types have realistic use cases that cannot be achieved with structures. 494 615 And having a pointer-to-tuple type potentially forbids the simple offset-array implementation of variadic polymorphism. 495 616 For example, in the case where a type assertion requests the pointer type @TT *@ in the above example, it forces the tuple type to be a @struct@, and thus incurring a high cost. 496 617 My conclusion is that tuples should not be structured (first-class), rather they should be unstructured. 497 This agrees with Rodolfo's original descri bes618 This agrees with Rodolfo's original description: 498 619 \begin{quote} 499 620 As such, their [tuples] use does not enforce a particular memory layout, and in particular, does not guarantee that the components of a tuple occupy a contiguous region of memory.~\cite[pp.~74--75]{Esteves04} … … 509 630 However, this forces the programer to use a tuple variable and possibly a tuple type to support a constructor, when they actually want separate variables with separate constructors. 510 631 And as stated previously, type variables (structured tuples) are rare in general \CFA programming so far. 511 To address this issue, while retaining the ability to leverage constructors, the following new tuple-like declaration syntax is proposed.632 To address this issue, while retaining the ability to leverage constructors, I proposed the following new tuple-like declaration syntax. 512 633 \begin{cfa} 513 634 [ int x, int y ] = gives_two(); … … 521 642 \end{cfa} 522 643 and the implementation performs as much copy elision as possible. 644 Currently, this new declaration form is parsed by \CFA, showing its syntax is viable, but it is unimplemented because of downstream resolver issues. 523 645 524 646 … … 526 648 \label{s:inlineSubstructure} 527 649 528 As mentioned \see{\VRef[Figure]{f:Nesting}}, C allows an anonymous aggregate type (@struct@ or @union@) to be embedded (nested) within another one, \eg a tagged union.650 As mentioned, C allows an anonymous aggregate type (@struct@ or @union@) to be embedded (nested) within another one \see{\VRef[Figure]{f:Nesting}}, \eg a tagged union. 529 651 \begin{cfa} 530 652 struct S { 531 653 unsigned int tag; 532 union { $\C{// anonymous nested aggregate}$654 union { // anonymous nested aggregate 533 655 int x; double y; char z; 534 656 }; 535 657 } s; 536 658 \end{cfa} 537 The @union@ field-names are hoisted into the @struct@, so there is direct access, \eg @s.x@; 538 hence, field names must be unique. 539 For a nested anonymous @struct@, both field names and values are hoisted. 659 Here, the @union@ combines its field into a common block of storage, and because there is no variable-name overloading in C, all of the union field names must be unique. 660 Furthermore, because the union is unnamed, these field-names are hoisted into the @struct@, giving direct access, \eg @s.x@; 661 hence, the union field names must be unique with the structure field names. 662 The same semantics applies to a nested anonymous @struct@: 540 663 \begin{cquote} 541 664 \begin{tabular}{@{}l@{\hspace{35pt}}l@{}} … … 556 679 \end{tabular} 557 680 \end{cquote} 558 559 As an aside, C nested \emph{named} aggregates behave in a (mysterious) way because the nesting is allowed but there is no ability to use qualification to access an inner type, like the \CC type operator `@::@'. 560 \emph{In fact, all named nested aggregates are hoisted to global scope, regardless of the nesting depth.} 681 However, unlike the union which provides storage sharing, there is no semantic difference between the nested anonymous structure and its rewritten counterpart. 682 Hence, the nested anonymous structure provides no useful capability. 683 684 Nested \emph{named} aggregates are allowed in C but there is no qualification operator, like the \CC type operator `@::@', to access an inner type. 685 \emph{To compensate for the missing type operator, all named nested aggregates are hoisted to global scope, regardless of the nesting depth, and type usages within the nested type are replaced with global type name.} 686 Hoisting nested types can result in name collisions among types at the global level, which defeats the purpose of nesting the type. 687 \VRef[Figure]{f:NestedNamedAggregate} shows the nested type @T@ is hoisted to the global scope and the declaration rewrites within structure @S@. 688 Hence, the possible accesses are: 689 \begin{cfa} 690 struct S s; 691 s.i = 1; 692 s.t.i = 2; 693 s.w = (struct T){ 7, 8 }; 694 struct T x = { 5, 6 }; // use (un)nested type name 695 s.t = (struct T){ 2, 3 }; 696 \end{cfa} 697 where @T@ is used without qualification even though it is nested in @S@. 698 It is for these reasons that nested types are not used in C, and if used, are extremely confusing. 699 700 \begin{figure} 561 701 \begin{cquote} 562 702 \begin{tabular}{@{}l@{\hspace{35pt}}l@{}} … … 564 704 \begin{cfa} 565 705 struct S { 566 struct T{706 @struct T@ { 567 707 int i, j; 568 } ;569 struct U {570 int k, l;571 572 }; 708 } t; // warning without declaration 709 struct T w; 710 int k; 711 }; 712 573 713 \end{cfa} 574 714 & 575 715 \begin{cfa} 576 struct T{716 @struct T@ { 577 717 int i, j; 578 718 }; 579 struct U {580 int k, l;581 };582 719 struct S { 720 @struct T t@; 721 struct T w; 722 int k; 583 723 }; 584 724 \end{cfa} 585 725 \end{tabular} 586 726 \end{cquote} 587 Hence, the possible accesses are: 588 \begin{cfa} 589 struct S s; // s cannot access any fields 590 struct T t; t.i; t.j; 591 struct U u; u.k; u.l; 592 \end{cfa} 593 and the hoisted type names can clash with global type names. 727 \caption{Nested Named Aggregate} 728 \label{f:NestedNamedAggregate} 729 \end{figure} 730 594 731 For good reasons, \CC chose to change this semantics: 595 732 \begin{cquote} … … 604 741 \hfill ISO/IEC 14882:1998 (\CC Programming Language Standard)~\cite[C.1.2.3.3]{ANSI98:C++} 605 742 \end{cquote} 606 However, there is no syntax to access from a variable through a type to a field.607 \begin{cfa}608 struct S s; @s::T@.i; @s::U@.k;609 \end{cfa}610 743 \CFA chose to adopt the \CC non-compatible change for nested types, since \CC's change has already forced certain coding changes in C libraries that must be parsed by \CC. 611 744 \CFA also added the ability to access from a variable through a type to a field. 612 745 \begin{cfa} 613 struct S s; @s.T@.i; @s.U@.k; 614 \end{cfa} 746 struct S s; @s.i@; @s.T@.i; 747 \end{cfa} 748 See the use case for this feature at the end of this section. 615 749 616 750 % https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html 617 751 618 A polymorphic extension to nested aggregates appears in the Plan-9 C dialect, used in the Bell Labs' Plan-9 research operating 752 A polymorphic extension to nested aggregates appears in the Plan-9 C dialect, used in the Bell Labs' Plan-9 research operating-system. 619 753 The feature is called \newterm{unnamed substructures}~\cite[\S~3.3]{Thompson90new}, which continues to be supported by @gcc@ and @clang@ using the extension (@-fplan9-extensions@). 620 The goal is to provided the same effect of thenested aggregate with the aggregate type defined elsewhere, which requires it be named.754 The goal is to provided the same effect as a nested aggregate with the aggregate type defined elsewhere, which requires it be named. 621 755 \begin{cfa} 622 756 union U { $\C{// unnested named}$ … … 633 767 \end{cfa} 634 768 Note, the position of the substructure is normally unimportant, unless there is some form of memory or @union@ overlay. 635 Like an anonymous nested type, a named nested Plan-9type has its field names hoisted into @struct S@, so there is direct access, \eg @s.x@ and @s.i@.769 Like an anonymous nested type, a named Plan-9 nested type has its field names hoisted into @struct S@, so there is direct access, \eg @s.x@ and @s.i@. 636 770 Hence, the field names must be unique, unlike \CC nested types, but the type names are at a nested scope level, unlike type nesting in C. 637 771 In addition, a pointer to a structure is automatically converted to a pointer to an anonymous field for assignments and function calls, providing containment inheritance with implicit subtyping, \ie @U@ $\subset$ @S@ and @W@ $\subset$ @S@, \eg: … … 689 823 However, the Plan-9 semantics allow implicit conversions from the outer type to the inner type, which means the \CFA type resolver must take this information into account. 690 824 Therefore, the \CFA resolver must implement the Plan-9 features and insert necessary type conversions into the translated code output. 691 In the current version of \CFA, this is the only kind of implicit type conversion other than the standard C conversions.825 In the current version of \CFA, this is the only kind of implicit type conversion other than the standard C arithmetic conversions. 692 826 693 827 Plan-9 polymorphism can result in duplicate field names. … … 714 848 and again the expression @d.x@ is ambiguous. 715 849 While \CC has no direct syntax to disambiguate @x@, \ie @d.B.x@ or @d.C.x@, it is possible with casts, @((B)d).x@ or @((C)d).x@. 716 Like \CC, \CFA compiles the Plan-9 version and provides direct syntaxand casts to disambiguate @x@.850 Like \CC, \CFA compiles the Plan-9 version and provides direct qualification and casts to disambiguate @x@. 717 851 While ambiguous definitions are allowed, duplicate field names is poor practice and should be avoided if possible. 718 However, when a programmer does not control all code, this problem can occur and a naming workaround shouldexist.852 However, when a programmer does not control all code, this problem can occur and a naming workaround must exist.
Note: See TracChangeset
for help on using the changeset viewer.