| [3c2c2f0] | 1 | #include <assert.h>
 | 
|---|
 | 2 | 
 | 
|---|
 | 3 | forall( tE & ) {
 | 
|---|
 | 4 | 
 | 
|---|
 | 5 |     struct dlink{
 | 
|---|
 | 6 |         tE *next;
 | 
|---|
 | 7 |         tE *prev;
 | 
|---|
 | 8 |     };
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 |     static inline void ?{}( dlink(tE) & this ) {
 | 
|---|
 | 11 |         this.next = 0p;
 | 
|---|
 | 12 |         this.prev = 0p;
 | 
|---|
 | 13 |     }
 | 
|---|
 | 14 | 
 | 
|---|
 | 15 |     forall( tLinks & = dlink(tE) ) {
 | 
|---|
 | 16 |         struct dlist{
 | 
|---|
 | 17 |             tE *first;
 | 
|---|
 | 18 |             tE *last;
 | 
|---|
 | 19 |         };
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 |         static inline void ?{}( dlist(tE, tLinks) & this ) {
 | 
|---|
 | 22 |             this.first = 0p;
 | 
|---|
 | 23 |             this.last = 0p;
 | 
|---|
 | 24 |         }
 | 
|---|
 | 25 |     }
 | 
|---|
 | 26 | }
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | trait embedded( tOuter &, tInner & ) {
 | 
|---|
 | 29 |     tInner & ?`inner( tOuter & );
 | 
|---|
 | 30 | };
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | // embedded is reflexive
 | 
|---|
 | 33 | forall( tX & )
 | 
|---|
 | 34 | static inline tX & ?`inner( tX & this ) { return this; }
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 | // use this on every case of plan-9 inheritance, to make embedded a closure of plan-9 inheritance
 | 
|---|
 | 37 | #define P9_EMBEDDED( tOuter, tInner ) \
 | 
|---|
 | 38 |     static inline tInner & ?`inner( tOuter & this ) { return this; }
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 | forall( tE &, tLinks & | embedded( tE, tLinks ) | embedded( tLinks, dlink(tE) ) ) {
 | 
|---|
 | 42 |     static inline void insert_last( dlist(tE, tLinks) &lst, tE & e ) {
 | 
|---|
 | 43 |         if (lst.last) {
 | 
|---|
 | 44 |             verify(lst.first);
 | 
|---|
 | 45 |             dlink(tE) & oldLastLinks = (*lst.last)`inner`inner;
 | 
|---|
 | 46 |             verify(oldLastLinks.next == 0p);
 | 
|---|
 | 47 |             oldLastLinks.next = & e;
 | 
|---|
 | 48 |         } else {
 | 
|---|
 | 49 |             verify(!lst.first);
 | 
|---|
 | 50 |             lst.first = &e;
 | 
|---|
 | 51 |         }
 | 
|---|
 | 52 |         dlink(tE) & newLastLinks = e`inner`inner;
 | 
|---|
 | 53 |         verify(newLastLinks.prev == 0p);
 | 
|---|
 | 54 |         verify(newLastLinks.next == 0p);
 | 
|---|
 | 55 |         newLastLinks.prev = lst.last;
 | 
|---|
 | 56 |         lst.last = &e;
 | 
|---|
 | 57 |     }
 | 
|---|
 | 58 |     static inline void remove_first( dlist(tE, tLinks) &lst ) {
 | 
|---|
 | 59 |         verify(lst.first && lst.last);
 | 
|---|
 | 60 |         dlink(tE) & oldFirstLinks = (*lst.first)`inner`inner;
 | 
|---|
 | 61 |         verify(oldFirstLinks.prev == 0p);
 | 
|---|
 | 62 |         if( lst.last != lst.first) {
 | 
|---|
 | 63 |             verify(oldFirstLinks.next != 0p);
 | 
|---|
 | 64 |             tE & newFirst = * oldFirstLinks.next;
 | 
|---|
 | 65 |             dlink(tE) & newFirstLinks = (newFirst)`inner`inner;
 | 
|---|
 | 66 |             oldFirstLinks.next = 0p;
 | 
|---|
 | 67 |             newFirstLinks.prev = 0p;
 | 
|---|
 | 68 |             lst.first = & newFirst;
 | 
|---|
 | 69 |         } else {
 | 
|---|
 | 70 |             verify(oldFirstLinks.next == 0p);
 | 
|---|
 | 71 |             lst.last = 0p;
 | 
|---|
 | 72 |             lst.first = 0p;
 | 
|---|
 | 73 |         }
 | 
|---|
 | 74 |     }
 | 
|---|
 | 75 | }
 | 
|---|