Changeset bb9897c for doc


Ignore:
Timestamp:
Apr 5, 2026, 9:25:22 AM (22 hours ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Parents:
e78d969
Message:

proofreading in front half of list chapter

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/mike_brooks_MMath/list.tex

    re78d969 rbb9897c  
    3030In the example, there are implicit conversions from @S@ to @U@ and @S@ to @W@, extracting the appropriate value or pointer for the substructure.
    3131\VRef[Figure]{f:DiamondInheritancePattern} shows complex multiple inheritance patterns are possible, like the \newterm{diamond pattern}~\cite[\S~6.1]{Stroustrup89}\cite[\S~4]{Cargill91}.
    32 Currently, \CFA type-system does not support @virtual@ inheritance.
     32Currently, the \CFA type-system does not support @virtual@ inheritance.
    3333
    3434\begin{figure}
     
    5555struct R : @public B@ { int r, w; };
    5656struct T : @public L, R@ { int t; };
    57 
     57                              T
     58               B      L          B      R
    5859T t = { { { 5 }, 3, 4 }, { { 8 }, 6, 7 }, 3 };
    5960t.t = 42;
     
    6869struct R { @inline B;@ int r, w; };
    6970struct T { @inline L; inline R;@ int t; };
    70 
     71                              T
     72               B      L          B      R
    7173T t = { { { 5 }, 3, 4 }, { { 8 }, 6, 7 }, 3 };
    7274t.t = 42;
     
    8890\subsection{Core Design Issues}
    8991
    90 The doubly-linked list attaches links intrusively, supports multiple link axes, integrates with user code via the type system, treats its ends uniformly, and identifies a list using an explicit head.
     92The doubly-linked list attaches links intrusively in a node, allows a node to appear on multiple lists (axes) simultaneously, integrates with user code via the type system, treats its ends uniformly, and identifies a list using an explicit head.
    9193This design covers system and data management issues stated in \VRef{toc:lst:issue}.
    9294
     
    128130\end{figure}
    129131
    130 \VRef[Figure]{fig:lst-features-multidir} shows how the \CFA library supports multi-inline links, so a node can be on one or more lists simultaneously (axes).
     132\VRef[Figure]{fig:lst-features-multidir} shows how the \CFA library supports multi-inline links, so a node has multiple axes.
    131133The declaration of @req@ has two inline-inheriting @dlink@ occurrences.
    132134The first of these gives a type named @req.by_pri@, @req@ inherits from it, and it inherits from @dlink@.
     
    135137
    136138The declarations of the list-head objects, @reqs_pri@, @reqs_rqr_42@, @reqs_rqr_17@, and @reqs_rqr_99@, bind which link nodes in @req@ are used by this list.
    137 Hence, the type of the variable @reqs_pri@, @dlist(req, req.by_pri)@, means operations called on @reqs_pri@ implicitly select (disambiguate) the correct @dlink@s, \eg the calls @insert_first(reqs_pri, ...)@ imply, ``here, we are working by priority.''
     139Hence, the type of the variable @reqs_pri@, @dlist(req, req.by_pri)@, means operations on @reqs_pri@ implicitly select (disambiguate) the correct @dlink@s, \eg the calls @insert_first(reqs_pri, ...)@ imply, ``here, we are working by priority.''
    138140As in \VRef[Figure]{fig:lst-issues-multi-static}, three lists are constructed, a priority list containing all nodes, a list with only nodes containing the value 42, and a list with only nodes containing the value 17.
    139141
    140142\begin{figure}
    141143\centering
     144
    142145\begin{tabular}{@{}ll@{}}
    143 \begin{tabular}{@{}l@{}}
    144     \lstinput{20-31}{lst-features-multidir.run.cfa} \\
    145     \lstinput{43-71}{lst-features-multidir.run.cfa}
    146     \end{tabular}
    147         &
    148         \lstinput[language=C++]{20-60}{lst-issues-multi-static.run.c}
     146\multicolumn{1}{c}{\CFA} &      \multicolumn{1}{c}{C} \\
     147        \begin{tabular}{@{}l@{}}
     148        \lstinput{20-31}{lst-features-multidir.run.cfa} \\
     149        \lstinput{43-71}{lst-features-multidir.run.cfa}
    149150        \end{tabular}
     151&
     152        \lstinput[language=C++]{20-60}{lst-issues-multi-static.run.c}
     153\end{tabular}
    150154
    151155\caption{
    152         Demonstration of multiple static link axes done in the \CFA list library.
    153         The right example is from \VRef[Figure]{fig:lst-issues-multi-static}.
    154                 The left \CFA example does the same job.
    155     }
    156     \label{fig:lst-features-multidir}
     156        Demonstration of multiple static link axes done in the \CFA list library.
     157        The right example is from \VRef[Figure]{fig:lst-issues-multi-static}.
     158        The left \CFA example does the same job.
     159}
     160\label{fig:lst-features-multidir}
    157161\end{figure}
    158162
     
    200204Finally, the library is separately compiled from the usage code, modulo inlining.
    201205
    202 The \CFA library works in headed and headless modes.
    203 \PAB{TODO: elaborate.}
    204 
    205206
    206207\section{List API}
     
    209210\begin{itemize}[leftmargin=*]
    210211\item
    211 @isListed@ returns true if the node is an element of a list and false otherwise.
    212 \item
    213 @isEmpty@ returns true if the list has no nodes and false otherwise.
     212@listed@ returns true if the node is an element of a list and false otherwise.
     213\item
     214@empty@ returns true if the list has no nodes and false otherwise.
    214215\item
    215216@first@ returns a reference to the first node of the list without removing it or @0p@ if the list is empty.
     
    231232@advance@ returns true if the iterator cursor is advanced to the next (successor, towards last) node after the prior cursor node and false otherwise.
    232233\item
    233 @isFirst@ returns true if the node is the first node in the list and false otherwise.
    234 \item
    235 @isLast@ returns true if the node is the last node in the list and false otherwise.
     234@first@ returns true if the node is the first node in the list and false otherwise.
     235\item
     236@last@ returns true if the node is the last node in the list and false otherwise.
    236237\item
    237238@pred@ returns a reference to the previous (predecessor, towards first) node before a specified node or @0p@ if a specified node is the first node in the list.
     
    252253The node must be in the @from@ list.
    253254\end{itemize}
     255For operations @insert_*@, @insert@, and @remove@, a variable-sized list of nodes can be specified using \CFA's tuple type~\cite[\S~4.7]{Moss18} (not discussed), \eg @insert( list, n1, n2, n3 )@, recursively invokes @insert( list, n@$_i$@ )@.\footnote{
     256Currently, a resolver bug between tuple types and references means tuple routines must use pointer parameters.
     257Nevertheless, the imaginary reference versions are used here as the code is cleaner, \eg no \lstinline{&} on call arguments.}
    254258
    255259\begin{figure}
    256260\begin{cfa}
    257 E & isListed( E & node );
    258 E & isEmpty( dlist( E ) & list );
     261E & listed( E & node );
     262E & empty( dlist( E ) & list );
    259263E & first( dlist( E ) & list );
    260264E & last( dlist( E ) & list );
     
    265269bool advance( E && refx );
    266270bool recede( E && refx );
    267 bool isFirst( E & node );
    268 bool isLast( E & node );
     271bool first( E & node );
     272bool last( E & node );
    269273E & prev( E & node );
    270274E & next( E & node );
    271275E & insert_first( dlist( E ) & list, E & node );
    272 E & insert_last( dlist( E ) & list, E & node );
     276E & insert_last( dlist( E ) & list, E & node ); // synonym insert
    273277E & remove_first( dlist( E ) & list );
    274278E & remove_last( dlist( E ) & list );
     
    284288
    285289It is possible to iterate through a list manually or using a set of standard macros.
    286 \VRef[Figure]{f:IteratorTemple} shows the iterator template, managing a list of nodes, used throughout the following iterator examples.
     290\VRef[Figure]{f:IteratorDriver} shows the iterator outline, managing a list of nodes, used throughout the following iterator examples.
    287291Each example assumes its loop body prints the value in the current node.
    288292
     
    291295#include <fstream.hfa>
    292296#include <list.hfa>
    293 
    294297struct node {
    295298        int v;
     
    299302        dlist(node) list;
    300303        node n1 = { 1 }, n2 = { 2 }, n3 = { 3 }, n4 = { 4 };
    301         insert( list, n1 );   insert( list, n2 );   insert( list, n3 );   insert( list, n4 );
     304        insert( list, n1, n2, n3, n4 );                                 $\C{// insert in any order}$
    302305        sout | nlOff;
    303         for ( ... ) @sout | it.v | ",";   sout | nl;@ // iterator examples in text
    304         remove( n1 );   remove( n2 );   remove( n3 );   remove( n4 );
     306        @for ( ... )@ sout | it.v | ",";   sout | nl;   $\C{// iterator examples in text}$
     307        remove( n1, n2, n3, n4 );                                       $\C{// remove in any order}$
    305308}
    306309\end{cfa}
    307 \caption{Iterator Temple}
    308 \label{f:IteratorTemple}
     310\caption{Iterator Driver}
     311\label{f:IteratorDriver}
    309312\end{figure}
    310313
     
    361364\end{tabular}
    362365\end{cquote}
    363 Iterating forward and reverse through the entire list using the shorthand start at the list head and pick a axis.
     366Iterating forward and reverse through the entire list using the shorthand start at the list head and pick an axis.
    364367In this case, @advance@ and @recede@ return a boolean, like \CC @while ( cin >> i )@.
    365368\begin{cquote}
     
    496499With this change, both @begin ~ end@ and @end@ (in context of the latter ``two-place for'' expression) parse as \emph{ranges}, and the loop syntax becomes, simply:
    497500\begin{cfa}
    498     for( elem; rangeExpr )
     501        for( elem; rangeExpr )
    499502\end{cfa}
    500503The expansion and underlying API are under discussion.
     
    517520
    518521
     522\section[C++ Lists]{\CC Lists}
     523
     524It is worth addressing two API issues in \CC lists avoided in \CFA.
     525First, \CC lists require two steps to remove a node versus one in \CFA.
     526\begin{cquote}
     527\begin{tabular}{@{}ll@{}}
     528\multicolumn{1}{c}{\CC} & \multicolumn{1}{c}{\CFA} \\
     529\begin{c++}
     530list<node> li;
     531node n = li.first();  // assignment could raise exception
     532li.pop_front();
     533\end{c++}
     534&
     535\begin{cfa}
     536dlist(node) list;
     537node n = remove_first( list );
     538
     539\end{cfa}
     540\end{tabular}
     541\end{cquote}
     542The argument for two steps is exception safety: returning an unknown T by value/move might throw an exception from T's copy/move constructor.
     543Hence, to be \emph{exception safe}, all internal list operations must complete before the copy/move so the list is consistent should the return fail.
     544This coding style can result in contrived code, but is usually possible;
     545however, it requires the container designer to anticipate the potential throw.
     546(Note, this anticipation issue is pervasive in exception systems, not just with containers.)
     547The solution moves the coding complexity from the container designer to the programer~\cite[ch~10, part 3]{Sutter99}.
     548First, obtain the node, which might fail, but the container is unmodified.
     549Second, remove the node, which modifies the container without the possibly of an exception.
     550This movement of responsibility increases the cognitive effort for programmers.
     551Unfortunately, this \emph{single-responsibility principle}, \ie preferring separate operations, is often repeated as a necessary requirement rather an an optional one.
     552Separate operations should always be available, but their composition should also be available.
     553Interestingly, this issue does not apply to intrusive lists, because the node data is never copied/moved in or out of a list;
     554only the link fields are accessed in list operations.
     555
     556Second, \VRef[Figure]{f:CCvsCFAListIssues} shows an example where a \CC list operation is $O(N$) rather than $O(1)$ in \CFA.
     557This issue is inherent to wrapped (non-intrusive) lists.
     558Specifically, to remove a node requires access to the links that materialize its membership.
     559In a wrapped list, there is no access from node to links, and for abstract reasons, no direct pointers to wrapped nodes, so the links must be found indirectly by navigating the list.
     560The \CC iterator is the abstraction to navigate wrapped links.
     561So an iterator is needed, not because it offers go-next, but for managing the list membership.
     562Note, attempting to keep an array of iterators to each node requires high-complexity to ensure the list and array are harmonized.
     563
     564\begin{figure}
     565\begin{tabular}{@{}ll@{}}
     566\multicolumn{1}{c}{\CC} & \multicolumn{1}{c}{\CFA} \\
     567\begin{c++}
     568list<node *> list;
     569node n1 = { 1 }, n2 = { 2 }, n3 = { 3 }, n4 = { 4 };
     570list.push_back( &n1 );  list.push_back( &n2 );
     571list.push_back( &n3 );  list.push_back( &n4 );
     572list<node *>::iterator it;
     573for ( it = list.begin(); it != list.end(); it ++ )
     574        if ( *it == &n3 ) { dl.erase( it ); break; }
     575\end{c++}
     576&
     577\begin{cfa}
     578dlist(node) list;
     579node n1 = { 1 }, n2 = { 2 }, n3 = { 3 }, n4 = { 4 };
     580insert( list, n1, n2, n3, n4 );
     581
     582
     583
     584remove( list, n3 );
     585\end{cfa}
     586\end{tabular}
     587\caption{\CC \vs \CFA List Issues}
     588\label{f:CCvsCFAListIssues}
     589\end{figure}
     590
     591\begin{comment}
     592Dave Dice:
     593There are what I'd call the "dark days" of C++, where the language \& libraries seemed to be getting progressively uglier - requiring more tokens to express something simple, and lots of arcana.
     594But over time, somehow, they seem to have mostly righted the ship and now I can write C++ code that's fairly terse, like python, by ignoring all the old constructs.
     595(They carry around the legacy baggage, of course, but seemed to have found a way to evolve away from it).
     596
     597If you just want to traverse a std::list, then, using modern "for" loops, you never need to see an iterator.
     598I try hard never to need to write X.begin() or X.end().
     599(There are situations where I'll expose iterators for my own types, however, to enable modern "for" loops).
     600If I'm implementing simple linked lists, I'll usually skip std:: collections and do it myself, as it's less grief.
     601I just don't get that much advantage from std::list.  And my code is certainly not any shorter.
     602On the other hand, @std::map@, @unordered_map@, @set@, and friends, are terrific, and I can usually still avoid seeing any iterators, which are blight to the eye.
     603So those are a win and I get to move up an abstraction level, and write terse but easily understood code that still performs well.
     604(One slight concern here is that all the C++ collection/container code is templated and lives in include files, and not traditional libraries.
     605So the only way to replace something - say with a better algorithm, or you have a bug in the collections code - is to boil the oceans and recompile everything.
     606But on the other hand the compiler can specialize to the specific use case, which is often a nice performance win).
     607
     608And yeah, the method names are pretty terrible.  I think they boxed themselves in early with a set of conventions that didn't age well, and they tried to stick with it and force regularity over the collection types.
     609
     610I've never seen anything written up about the history, although lots of the cppcon talks make note of the "bad old days" idea and how collection \& container library design evolved.   The issue is certainly recognized.
     611\end{comment}
     612
     613
    519614\section{Implementation}
    520615
    521 \VRef[Figure]{fig:lst-impl-links} continues the running @req@ example, now showing the \CFA list library's internal representation.
     616\VRef[Figure]{fig:lst-impl-links} continues the running @req@ example, showing the \CFA list library's internal representation.
    522617The @dlink@ structure contains exactly two pointers: @next@ and @prev@, which are opaque.
    523 Even though the user-facing list model is linear, the CFA library implements all listing as circular.
    524 This choice helps achieve uniform end treatment and \PAB{TODO finish summarizing benefit}.
     618Even though the user-facing list model is linear, the \CFA library implements all listing as circular.
     619This choice helps achieve uniform end treatment.
     620% and \PAB{TODO finish summarizing benefit}.
    525621A link pointer targets a neighbouring @dlink@ structure, rather than a neighbouring @req@.
    526622(Recall, the running example has the user putting a @dlink@ within a @req@.)
     
    530626        \includegraphics[width=\textwidth]{lst-impl-links.pdf}
    531627        \caption{
    532                 \CFA list library representations for the cases under discussion.
     628                \CFA list library representations for headed and headless lists.
    533629        }
    534630        \label{fig:lst-impl-links}
     
    540636Hence, the tags are set on the links that a user cannot navigate.
    541637
     638The \CFA library works in headed and headless modes.
    542639In a headed list, the list head (@dlist(req)@) acts as an extra element in the implementation-level circularly-linked list.
    543640The content of a @dlist@ header is a (private) @dlink@, with the @next@ pointer to the first element, and the @prev@ pointer to the last element.
     
    567664
    568665This experiment takes the position that:
    569 \begin{itemize}
    570     \item The total time to add and remove is relevant \vs individual times for add and remove.
    571           Adds without removes quickly fill memory;
     666\begin{itemize}[leftmargin=*]
     667        \item The total time to add and remove is relevant \vs individual times for add and remove.
     668                  Adds without removes quickly fill memory;
    572669                  removes without adds is meaningless.
    573     \item A relevant breakdown ``by operation'' is:
     670        \item A relevant breakdown ``by operation'' is:
    574671                \begin{description}
    575672                \item[movement]
    576           Is the add/remove applied to a stack, queue, or something else?
     673                  Is the add/remove applied to a stack, queue, or something else?
    577674                \item[polarity]
    578675                  In which direction does the action apply?
     
    580677                  For a stack, is the first or last end used for adding and removing?
    581678                \item[accessor]
    582           Is an add/remove location given by a list head's ``first''/``last'', or by a reference to an individual element?
     679                  Is an add/remove location given by a list head's first/last, or by a reference to an individual element?
    583680                \end{description}
    584     \item Speed differences caused by the host machine's memory hierarchy need to be identified and explained,
    585           but do not represent advantages of one linked-list implementation over another.
     681        \item Speed differences caused by the host machine's memory hierarchy need to be identified and explained,
     682                  but do not represent advantages of one linked-list implementation over another.
    586683\end{itemize}
    587684
     
    592689The experiment is sensitive enough to show:
    593690\begin{itemize}
    594     \item intrusive lists performing (majorly) differently than wrapped lists,
    595     \item a space of (minor) performance differences among the intrusive lists.
     691        \item intrusive lists performing (majorly) differently than wrapped lists,
     692        \item a space of (minor) performance differences among the intrusive lists.
    596693\end{itemize}
    597694
     
    637734To test list operations, the experiment performs the inserts/removes in different patterns, \eg insert and remove from front, insert from front and remove from back, random insert and remove, \etc.
    638735Unfortunately, the @std::list@ does \emph{not} support direct insert/remove from a node without an iterator, \ie no @erase( node )@, even though the list is doubly-linked.
    639 To eliminate the iterator, a trick is used for random insertions without replacement.
     736To eliminate the iterator, a trick is used for random insertions without replacement, which takes advantage of the array nature of the nodes.
    640737The @i@ fields in each node are initialized from @0..n-1@.
    641738These @i@ values are then shuffled in the nodes, and the @i@ value is used to represent an indirection to that node for insertion.
     
    761858  &
    762859  \subfloat[Linear List Nodes, AMD]{\label{f:Linear-swift}
    763     \hspace*{-0.75in}
    764     \includegraphics{plot-list-zoomout-noshuf-swift.pdf}
     860        \hspace*{-0.75in}
     861        \includegraphics{plot-list-zoomout-noshuf-swift.pdf}
    765862  } % subfigure
    766863  &
    767864  \subfloat[Linear List Nodes, Intel]{\label{f:Linear-java}
    768     \includegraphics{plot-list-zoomout-noshuf-java.pdf}
     865        \includegraphics{plot-list-zoomout-noshuf-java.pdf}
    769866  } % subfigure
    770867  \\
    771868  &
    772869  \subfloat[Shuffled List Nodes, AMD]{\label{f:Shuffled-swift}
    773     \hspace*{-0.75in}
    774     \includegraphics{plot-list-zoomout-shuf-swift.pdf}
     870        \hspace*{-0.75in}
     871        \includegraphics{plot-list-zoomout-shuf-swift.pdf}
    775872  } % subfigure
    776873  &
    777874  \subfloat[Shuffled List Nodes, Intel]{\label{f:Shuffled-java}
    778     \includegraphics{plot-list-zoomout-shuf-java.pdf}
     875        \includegraphics{plot-list-zoomout-shuf-java.pdf}
    779876  } % subfigure
    780877  \end{tabular}
     
    868965  &
    869966  \subfloat[Absolute Time, AMD]{\label{f:AbsoluteTime-swift}
    870     \hspace*{-0.75in}
    871     \includegraphics{plot-list-zoomin-abs-swift.pdf}
     967        \hspace*{-0.75in}
     968        \includegraphics{plot-list-zoomin-abs-swift.pdf}
    872969  } % subfigure
    873970  &
    874971  \subfloat[Absolute Time, Intel]{\label{f:AbsoluteTime-java}
    875     \includegraphics{plot-list-zoomin-abs-java.pdf}
     972        \includegraphics{plot-list-zoomin-abs-java.pdf}
    876973  } % subfigure
    877974  \\
    878975  &
    879976  \subfloat[Relative Time, AMD]{\label{f:RelativeTime-swift}
    880     \hspace*{-0.75in}
    881     \includegraphics{plot-list-zoomin-rel-swift.pdf}
     977        \hspace*{-0.75in}
     978        \includegraphics{plot-list-zoomin-rel-swift.pdf}
    882979  } % subfigure
    883980  &
    884981  \subfloat[Relative Time, Intel]{\label{f:RelativeTime-java}
    885     \includegraphics{plot-list-zoomin-rel-java.pdf}
     982        \includegraphics{plot-list-zoomin-rel-java.pdf}
    886983  } % subfigure
    887984  \end{tabular}
     
    9141011  &
    9151012  \subfloat[Supersets, AMD]{\label{f:Superset-swift}
    916     \hspace*{-0.75in}
    917     \includegraphics{plot-list-cmp-exout-swift.pdf}
     1013        \hspace*{-0.75in}
     1014        \includegraphics{plot-list-cmp-exout-swift.pdf}
    9181015  } % subfigure
    9191016  &
    9201017  \subfloat[Supersets, Intel]{\label{f:Superset-java}
    921     \includegraphics{plot-list-cmp-exout-java.pdf}
     1018        \includegraphics{plot-list-cmp-exout-java.pdf}
    9221019  } % subfigure
    9231020  \\
    9241021  &
    9251022  \subfloat[1st Level Slice, AMD]{\label{f:1stLevelSlice-swift}
    926     \hspace*{-0.75in}
    927     \includegraphics{plot-list-cmp-survey-swift.pdf}
     1023        \hspace*{-0.75in}
     1024        \includegraphics{plot-list-cmp-survey-swift.pdf}
    9281025  } % subfigure
    9291026  &
    9301027  \subfloat[1st Level Slice, Intel]{\label{f:1stLevelSlice-java}
    931     \includegraphics{plot-list-cmp-survey-java.pdf}
     1028        \includegraphics{plot-list-cmp-survey-java.pdf}
    9321029  } % subfigure
    9331030  \end{tabular}
     
    9811078
    9821079\begin{comment}
    983 \subsection{Result: CFA cost attribution}
     1080\subsection{Result: \CFA cost attribution}
    9841081
    9851082This comparison loosely itemizes the reasons that the \CFA implementation runs 15--20\% slower than LQ.
     
    10781175\label{toc:lst:futwork}
    10791176
    1080 The \CFA list examples elide the \lstinline{P9_EMBEDDED} annotations that (TODO: xref P9E future work) proposes to obviate.
     1177Not discussed in the chapter is an issue in the \CFA type system with Plan-9 @inline@ declarations.
     1178It implements the trait 'embedded' for the derived-base pair named in the arguments.
     1179This trait defines a pseudo conversion called backtick-inner, from derived to base (the safe direction).
     1180Such a real conversion exists for the concrete types, due to our compiler having the p9 language feature.
     1181But when trying to be polymorphic over the types, there is no way to access this built-in conversion, so my macro stands in until Fangren does more with conversions.
     1182
     1183An API author has decided that the intended user experience is:
     1184\begin{itemize}
     1185\item
     1186offer the user an opaque type that abstracts the API's internal state
     1187\item
     1188tell the user to extend this type
     1189\item
     1190provide functions with a ``user's type in, user's type out'' style
     1191\end{itemize}
     1192Fig XXX shows several attempts to provide this experience.
     1193The types in (a) give the setup, achieving the first two points, while the pair of function declarations and calls of (b) are unsuccessful attempts at achieving the third point.
     1194Both functions @f1@ and @f2@ allow calls of the form @f( d )@, but @f1@ has the wrong return type (@Base@) for initializing a @Derived@.
     1195The @f1@ signature fails to meet ``user's type out;'' this signature does not give the \emph{user} a usable type.
     1196On the other hand, the signature @f2@ offers the desired user experience, so the API author proceeds with trying to implement it.
     1197
     1198\begin{figure}
     1199\begin{cfa}
     1200#ifdef SHOW_ERRS
     1201#define E(...) __VA_ARGS__
     1202#else
     1203#define E(...)
     1204#endif
     1205
     1206// (a)
     1207struct Base { /*...*/ }; // system offers
     1208struct Derived { /*...*/ inline Base; }; // user writes
     1209
     1210// (b)
     1211// system offers
     1212Base & f1( Base & );
     1213forall( T ) T & f2( T & );
     1214// user writes
     1215void to_elide1() {
     1216        Derived & d /* = ... */;
     1217        f1( d );
     1218        E(  Derived & d1 = f1( d );  )  // error: return is not Derived
     1219        Derived & d2 = f2( d );
     1220
     1221        // (d), user could write
     1222        Base & b = d;
     1223}
     1224
     1225// (c), system has
     1226static void helper( Base & );
     1227forall( T ) T & f2( T & param ) {
     1228        E( helper( param );  )  // error: param is not Base
     1229        return param;
     1230}
     1231static void helper( Base & ) {}
     1232
     1233#include <list2.hfa>
     1234// (e)
     1235// system offers, has
     1236forall( T | embedded(T, Base, Base) )
     1237        T & f3( T & param ) {
     1238        helper( param`inner ); // ok
     1239        return param;
     1240}
     1241// user writes
     1242struct DerivedRedux { /*...*/ inline Base; };
     1243P9_EMBEDDED( DerivedRedux, Base )
     1244void to_elide2() {
     1245        DerivedRedux & dr /* = ... */;
     1246        DerivedRedux & dr3 = f3( dr );
     1247
     1248        // (f)
     1249        // user writes
     1250        Derived & xxx /* = ... */;
     1251        E(  Derived & yyy = f3( xxx );  )  // error: xxx is not embedded
     1252}
     1253\end{cfa}
     1254\end{figure}
     1255
     1256
     1257The \CFA list examples elide the @P9_EMBEDDED@ annotations that (TODO: xref P9E future work) proposes to obviate.
    10811258Thus, these examples illustrate a to-be state, free of what is to be historic clutter.
    10821259The elided portions are immaterial to the discussion and the examples work with the annotations provided.
     
    11101287P9_EMBEDDED(fred.yours, dlink(fred))
    11111288\end{cfa}
     1289
     1290
     1291The function definition in (c) gives this system-implementation attempt.
     1292The system needs to operate on its own data, stored in the @Base@ part of the user's @d@, now called @param@.
     1293Calling @helper@ represents this attempt to look inside.
     1294It fails, because the @f2@ signature does not state that @param@ has any relationship to @Base@;
     1295this signature does not give the \emph{system} a usable type.
     1296The fact that the user's argument can be converted to @Base@ is lost when going through this signature.
     1297
     1298Moving forward needs an @f@ signature that conveys the relationship that the argument @d@ has to @Base@.
     1299\CFA conveys type abilities, from caller to callee, by way of traits; so the challenge is to state the right trait member.
     1300As initialization (d) illustrates, the @d@--@Base@ capability is an implicit conversion.
     1301Unfortunately, in present state, \CFA does not have a first-class representation of an implicit conversion, the way operator @?{}@ (which is a value), done with the right overload, is arguably an explicit conversion.
     1302So \CFA cannot directly convey ``@T@ compatible with @Base@'' in a trait.
     1303
     1304This work contributes a stand-in for such an ability, tunneled through the present-state trait system, shown in (e).
     1305On the declaration/system side, the trait @embedded@, and its member, @`inner@, convey the ability to recover the @Base@, and thereby call @helper@.
     1306On the user side, the @P9_EMBEDDED@ macro accompanies type definitions that work with @f3@-style declarations.
     1307An option is presemt-state-available to compiler-emit @P9_EMBEDDED@ annotations automatically, upon each occurrence of an `inline` member.
     1308The choice not to is based on conversions in \CFA being a moving target because of separate, ongoing work.
     1309
     1310An intended finished state for this area is achieved if \CFA's future efforts with conversions include:
     1311\begin{itemize}
     1312\item
     1313treat conversion as operator(s), \ie values
     1314\item
     1315re-frame the compiler's current Plan-9 ``magic'' as seeking an implicit conversion operator, rather than seeking an @inline@ member
     1316\item
     1317make Plan-9 syntax cause an implementation of implicit conversion to exist (much as @struct@ syntax causes @forall(T)@ compliance to exist)
     1318\end{itemize}
     1319To this end, the contributed @P9_EMBEDDED@ expansion shows how to implement this conversion.
     1320
     1321
    11121322like in tests/list/dlist-insert-remove.
    11131323Future work should autogen those @P9_EMBEDDED@ declarations whenever it sees a plan-9 declaration.
Note: See TracChangeset for help on using the changeset viewer.